blob: 5ccb0e73a7a8a96327e6710bd7dddebbeb1d5f02 [file] [log] [blame]
youenn.fablet@crf.canon.fr6ebc90f2015-10-01 12:30:43 +00001/*
2 * Copyright (C) 2015 Canon Inc. All rights reserved.
calvaris@igalia.com7b05ff72015-10-20 09:51:09 +00003 * Copyright (C) 2015 Igalia.
youenn.fablet@crf.canon.fr6ebc90f2015-10-01 12:30:43 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
youenn.fablet@crf.canon.fr8255f492015-11-08 11:40:35 +000027// @internal
youenn.fablet@crf.canon.fr0cb09612015-10-09 14:21:58 +000028
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +000029function readableStreamReaderGenericInitialize(reader, stream)
30{
31 "use strict";
32
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000033 @putByIdDirectPrivate(reader, "ownerReadableStream", stream);
34 @putByIdDirectPrivate(stream, "reader", reader);
35 if (@getByIdDirectPrivate(stream, "state") === @streamReadable)
36 @putByIdDirectPrivate(reader, "closedPromiseCapability", @newPromiseCapability(@Promise));
37 else if (@getByIdDirectPrivate(stream, "state") === @streamClosed)
38 @putByIdDirectPrivate(reader, "closedPromiseCapability", { @promise: @Promise.@resolve() });
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +000039 else {
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000040 @assert(@getByIdDirectPrivate(stream, "state") === @streamErrored);
41 @putByIdDirectPrivate(reader, "closedPromiseCapability", { @promise: @newHandledRejectedPromise(@getByIdDirectPrivate(stream, "storedError")) });
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +000042 }
43}
44
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000045function privateInitializeReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +000046{
47 "use strict";
48
49 if (!@isReadableStream(stream))
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +000050 @throwTypeError("ReadableStreamDefaultController needs a ReadableStream");
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000051
52 // readableStreamController is initialized with null value.
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000053 if (@getByIdDirectPrivate(stream, "readableStreamController") !== null)
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +000054 @throwTypeError("ReadableStream already has a controller");
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000055
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000056 @putByIdDirectPrivate(this, "controlledReadableStream", stream);
57 @putByIdDirectPrivate(this, "underlyingSource", underlyingSource);
58 @putByIdDirectPrivate(this, "queue", @newQueue());
59 @putByIdDirectPrivate(this, "started", false);
60 @putByIdDirectPrivate(this, "closeRequested", false);
61 @putByIdDirectPrivate(this, "pullAgain", false);
62 @putByIdDirectPrivate(this, "pulling", false);
63 @putByIdDirectPrivate(this, "strategy", @validateAndNormalizeQueuingStrategy(size, highWaterMark));
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000064
youenn@apple.com81f51e32020-06-17 08:55:55 +000065 return this;
66}
67
68// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller, starting from step 6.
69// The other part is implemented in privateInitializeReadableStreamDefaultController.
70function setupReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, startMethod, pullMethod, cancelMethod)
71{
72 "use strict";
73 const controller = new @ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, @isReadableStream);
74 const startAlgorithm = () => @promiseInvokeOrNoopMethodNoCatch(underlyingSource, startMethod, [controller]);
75 const pullAlgorithm = () => @promiseInvokeOrNoopMethod(underlyingSource, pullMethod, [controller]);
76 const cancelAlgorithm = (reason) => @promiseInvokeOrNoopMethod(underlyingSource, cancelMethod, [reason]);
77
78 @putByIdDirectPrivate(controller, "pullAlgorithm", pullAlgorithm);
79 @putByIdDirectPrivate(controller, "cancelAlgorithm", cancelAlgorithm);
80 @putByIdDirectPrivate(controller, "pull", @readableStreamDefaultControllerPull);
81 @putByIdDirectPrivate(controller, "cancel", @readableStreamDefaultControllerCancel);
82 @putByIdDirectPrivate(stream, "readableStreamController", controller);
83
84 startAlgorithm().@then(() => {
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000085 @putByIdDirectPrivate(controller, "started", true);
86 @assert(!@getByIdDirectPrivate(controller, "pulling"));
87 @assert(!@getByIdDirectPrivate(controller, "pullAgain"));
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +000088 @readableStreamDefaultControllerCallPullIfNeeded(controller);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000089 }, (error) => {
youenn@apple.com525b5862018-05-15 05:35:25 +000090 @readableStreamDefaultControllerError(controller, error);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000091 });
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +000092}
93
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +000094function readableStreamDefaultControllerError(controller, error)
95{
96 "use strict";
97
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +000098 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
youenn@apple.com525b5862018-05-15 05:35:25 +000099 if (@getByIdDirectPrivate(stream, "state") !== @streamReadable)
100 return;
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000101 @putByIdDirectPrivate(controller, "queue", @newQueue());
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000102 @readableStreamError(stream, error);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000103}
104
commit-queue@webkit.org48672fa2017-09-01 22:53:23 +0000105function readableStreamPipeTo(stream, sink)
106{
107 "use strict";
108 @assert(@isReadableStream(stream));
109
110 const reader = new @ReadableStreamDefaultReader(stream);
111
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000112 @getByIdDirectPrivate(reader, "closedPromiseCapability").@promise.@then(() => { }, (e) => { sink.error(e); });
commit-queue@webkit.org48672fa2017-09-01 22:53:23 +0000113
114 function doPipe() {
115 @readableStreamDefaultReaderRead(reader).@then(function(result) {
116 if (result.done) {
117 sink.close();
118 return;
119 }
120 try {
121 sink.enqueue(result.value);
122 } catch (e) {
123 sink.error("ReadableStream chunk enqueueing in the sink failed");
124 return;
125 }
126 doPipe();
youenn@apple.comfb6116e2019-08-06 00:36:09 +0000127 }, function(e) {
128 sink.error(e);
commit-queue@webkit.org48672fa2017-09-01 22:53:23 +0000129 });
130 }
131 doPipe();
132}
133
youenn@apple.com9c9fe062020-08-25 17:36:58 +0000134function acquireReadableStreamDefaultReader(stream)
135{
136 return new @ReadableStreamDefaultReader(stream);
137}
138
139// FIXME: Replace readableStreamPipeTo by below function.
140// This method implements the latest https://streams.spec.whatwg.org/#readable-stream-pipe-to.
141function readableStreamPipeToWritableStream(source, destination, preventClose, preventAbort, preventCancel, signal)
142{
143 @assert(@isReadableStream(source));
144 @assert(@isWritableStream(destination));
145 @assert(!@isReadableStreamLocked(source));
146 @assert(!@isWritableStreamLocked(destination));
shvaikalesh@gmail.comb1828892021-08-04 04:49:52 +0000147 @assert(signal === @undefined || @isAbortSignal(signal));
youenn@apple.com9c9fe062020-08-25 17:36:58 +0000148
149 if (@getByIdDirectPrivate(source, "underlyingByteSource") !== @undefined)
150 return @Promise.@reject("Piping of readable by strean is not supported");
151
152 let pipeState = { source : source, destination : destination, preventAbort : preventAbort, preventCancel : preventCancel, preventClose : preventClose, signal : signal };
153
154 pipeState.reader = @acquireReadableStreamDefaultReader(source);
155 pipeState.writer = @acquireWritableStreamDefaultWriter(destination);
156
157 @putByIdDirectPrivate(source, "disturbed", true);
158
youenn@apple.come0e61102020-08-26 18:07:35 +0000159 pipeState.finalized = false;
youenn@apple.com9c9fe062020-08-25 17:36:58 +0000160 pipeState.shuttingDown = false;
161 pipeState.promiseCapability = @newPromiseCapability(@Promise);
162 pipeState.pendingReadPromiseCapability = @newPromiseCapability(@Promise);
163 pipeState.pendingReadPromiseCapability.@resolve.@call();
164 pipeState.pendingWritePromise = @Promise.@resolve();
165
youenn@apple.come0e61102020-08-26 18:07:35 +0000166 if (signal !== @undefined) {
167 const algorithm = () => {
168 if (pipeState.finalized)
169 return;
170
171 const error = @makeDOMException("AbortError", "abort pipeTo from signal");
172
173 @pipeToShutdownWithAction(pipeState, () => {
174 const shouldAbortDestination = !pipeState.preventAbort && @getByIdDirectPrivate(pipeState.destination, "state") === "writable";
175 const promiseDestination = shouldAbortDestination ? @writableStreamAbort(pipeState.destination, error) : @Promise.@resolve();
176
177 const shouldAbortSource = !pipeState.preventCancel && @getByIdDirectPrivate(pipeState.source, "state") === @streamReadable;
178 const promiseSource = shouldAbortSource ? @readableStreamCancel(pipeState.source, error) : @Promise.@resolve();
179
180 let promiseCapability = @newPromiseCapability(@Promise);
181 let shouldWait = true;
182 let handleResolvedPromise = () => {
183 if (shouldWait) {
184 shouldWait = false;
185 return;
186 }
187 promiseCapability.@resolve.@call();
188 }
189 let handleRejectedPromise = (e) => {
190 promiseCapability.@reject.@call(@undefined, e);
191 }
192 promiseDestination.@then(handleResolvedPromise, handleRejectedPromise);
193 promiseSource.@then(handleResolvedPromise, handleRejectedPromise);
194 return promiseCapability.@promise;
195 }, error);
196 };
commit-queue@webkit.org957f6f52021-07-07 03:12:05 +0000197 if (@whenSignalAborted(signal, algorithm))
youenn@apple.come0e61102020-08-26 18:07:35 +0000198 return pipeState.promiseCapability.@promise;
199 }
youenn@apple.com9c9fe062020-08-25 17:36:58 +0000200
201 @pipeToErrorsMustBePropagatedForward(pipeState);
202 @pipeToErrorsMustBePropagatedBackward(pipeState);
203 @pipeToClosingMustBePropagatedForward(pipeState);
204 @pipeToClosingMustBePropagatedBackward(pipeState);
205
206 @pipeToLoop(pipeState);
207
208 return pipeState.promiseCapability.@promise;
209}
210
211function pipeToLoop(pipeState)
212{
213 if (pipeState.shuttingDown)
214 return;
215
216 @pipeToDoReadWrite(pipeState).@then((result) => {
217 if (result)
218 @pipeToLoop(pipeState);
219 });
220}
221
222function pipeToDoReadWrite(pipeState)
223{
224 @assert(!pipeState.shuttingDown);
225
226 pipeState.pendingReadPromiseCapability = @newPromiseCapability(@Promise);
227 @getByIdDirectPrivate(pipeState.writer, "readyPromise").@promise.@then(() => {
228 if (pipeState.shuttingDown) {
229 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, false);
230 return;
231 }
232
233 @readableStreamDefaultReaderRead(pipeState.reader).@then((result) => {
234 const canWrite = !result.done && @getByIdDirectPrivate(pipeState.writer, "stream") !== @undefined;
235 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, canWrite);
236 if (!canWrite)
237 return;
238
239 pipeState.pendingWritePromise = @writableStreamDefaultWriterWrite(pipeState.writer, result.value);
240 }, (e) => {
241 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, false);
242 });
243 }, (e) => {
244 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, false);
245 });
246 return pipeState.pendingReadPromiseCapability.@promise;
247}
248
249function pipeToErrorsMustBePropagatedForward(pipeState)
250{
251 const action = () => {
252 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, false);
253 const error = @getByIdDirectPrivate(pipeState.source, "storedError");
254 if (!pipeState.preventAbort) {
255 @pipeToShutdownWithAction(pipeState, () => @writableStreamAbort(pipeState.destination, error), error);
256 return;
257 }
258 @pipeToShutdown(pipeState, error);
259 };
260
261 if (@getByIdDirectPrivate(pipeState.source, "state") === @streamErrored) {
262 action();
263 return;
264 }
265
266 @getByIdDirectPrivate(pipeState.reader, "closedPromiseCapability").@promise.@then(@undefined, action);
267}
268
269function pipeToErrorsMustBePropagatedBackward(pipeState)
270{
271 const action = () => {
272 const error = @getByIdDirectPrivate(pipeState.destination, "storedError");
273 if (!pipeState.preventCancel) {
274 @pipeToShutdownWithAction(pipeState, () => @readableStreamCancel(pipeState.source, error), error);
275 return;
276 }
277 @pipeToShutdown(pipeState, error);
278 };
279 if (@getByIdDirectPrivate(pipeState.destination, "state") === "errored") {
280 action();
281 return;
282 }
283 @getByIdDirectPrivate(pipeState.writer, "closedPromise").@promise.@then(@undefined, action);
284}
285
286function pipeToClosingMustBePropagatedForward(pipeState)
287{
288 const action = () => {
289 pipeState.pendingReadPromiseCapability.@resolve.@call(@undefined, false);
290 const error = @getByIdDirectPrivate(pipeState.source, "storedError");
291 if (!pipeState.preventClose) {
292 @pipeToShutdownWithAction(pipeState, () => @writableStreamDefaultWriterCloseWithErrorPropagation(pipeState.writer));
293 return;
294 }
295 @pipeToShutdown(pipeState);
296 };
297 if (@getByIdDirectPrivate(pipeState.source, "state") === @streamClosed) {
298 action();
299 return;
300 }
301 @getByIdDirectPrivate(pipeState.reader, "closedPromiseCapability").@promise.@then(action, @undefined);
302}
303
304function pipeToClosingMustBePropagatedBackward(pipeState)
305{
306 if (!@writableStreamCloseQueuedOrInFlight(pipeState.destination) && @getByIdDirectPrivate(pipeState.destination, "state") !== "closed")
307 return;
308
309 // @assert no chunks have been read/written
310
311 const error = @makeTypeError("closing is propagated backward");
312 if (!pipeState.preventCancel) {
313 @pipeToShutdownWithAction(pipeState, () => @readableStreamCancel(pipeState.source, error), error);
314 return;
315 }
316 @pipeToShutdown(pipeState, error);
317}
318
319function pipeToShutdownWithAction(pipeState, action)
320{
321 if (pipeState.shuttingDown)
322 return;
323
324 pipeState.shuttingDown = true;
325
326 const hasError = arguments.length > 2;
327 const error = arguments[2];
328 const finalize = () => {
329 const promise = action();
330 promise.@then(() => {
331 if (hasError)
332 @pipeToFinalize(pipeState, error);
333 else
334 @pipeToFinalize(pipeState);
335 }, (e) => {
336 @pipeToFinalize(pipeState, e);
337 });
338 };
339
340 if (@getByIdDirectPrivate(pipeState.destination, "state") === "writable" && !@writableStreamCloseQueuedOrInFlight(pipeState.destination)) {
341 pipeState.pendingReadPromiseCapability.@promise.@then(() => {
342 pipeState.pendingWritePromise.@then(finalize, finalize);
343 }, (e) => @pipeToFinalize(pipeState, e));
344 return;
345 }
346
347 finalize();
348}
349
350function pipeToShutdown(pipeState)
351{
352 if (pipeState.shuttingDown)
353 return;
354
355 pipeState.shuttingDown = true;
356
357 const hasError = arguments.length > 1;
358 const error = arguments[1];
359 const finalize = () => {
360 if (hasError)
361 @pipeToFinalize(pipeState, error);
362 else
363 @pipeToFinalize(pipeState);
364 };
365
366 if (@getByIdDirectPrivate(pipeState.destination, "state") === "writable" && !@writableStreamCloseQueuedOrInFlight(pipeState.destination)) {
367 pipeState.pendingReadPromiseCapability.@promise.@then(() => {
368 pipeState.pendingWritePromise.@then(finalize, finalize);
369 }, (e) => @pipeToFinalize(pipeState, e));
370 return;
371 }
372 finalize();
373}
374
375function pipeToFinalize(pipeState)
376{
377 @writableStreamDefaultWriterRelease(pipeState.writer);
378 @readableStreamReaderGenericRelease(pipeState.reader);
379
youenn@apple.come0e61102020-08-26 18:07:35 +0000380 // Instead of removing the abort algorithm as per spec, we make it a no-op which is equivalent.
381 pipeState.finalized = true;
youenn@apple.com9c9fe062020-08-25 17:36:58 +0000382
383 if (arguments.length > 1)
384 pipeState.promiseCapability.@reject.@call(@undefined, arguments[1]);
385 else
386 pipeState.promiseCapability.@resolve.@call();
387}
388
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000389function readableStreamTee(stream, shouldClone)
youenn.fablet@crf.canon.fr6ebc90f2015-10-01 12:30:43 +0000390{
391 "use strict";
392
youenn.fablet@crf.canon.frd6e3fa32015-11-09 18:06:51 +0000393 @assert(@isReadableStream(stream));
394 @assert(typeof(shouldClone) === "boolean");
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000395
commit-queue@webkit.orgba16f552016-07-27 10:40:17 +0000396 const reader = new @ReadableStreamDefaultReader(stream);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000397
calvaris@igalia.com3e2838f2015-11-10 15:45:21 +0000398 const teeState = {
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000399 closedOrErrored: false,
400 canceled1: false,
401 canceled2: false,
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +0000402 reason1: @undefined,
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000403 reason2: @undefined,
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000404 };
405
ysuzuki@apple.com357f5dd2020-06-08 21:07:22 +0000406 teeState.cancelPromiseCapability = @newPromiseCapability(@Promise);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000407
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000408 const pullFunction = @readableStreamTeePullFunction(teeState, reader, shouldClone);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000409
youenn@apple.com81f51e32020-06-17 08:55:55 +0000410 const branch1Source = { };
411 @putByIdDirectPrivate(branch1Source, "pull", pullFunction);
412 @putByIdDirectPrivate(branch1Source, "cancel", @readableStreamTeeBranch1CancelFunction(teeState, stream));
413
414 const branch2Source = { };
415 @putByIdDirectPrivate(branch2Source, "pull", pullFunction);
416 @putByIdDirectPrivate(branch2Source, "cancel", @readableStreamTeeBranch2CancelFunction(teeState, stream));
417
418 const branch1 = new @ReadableStream(branch1Source);
419 const branch2 = new @ReadableStream(branch2Source);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000420
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000421 @getByIdDirectPrivate(reader, "closedPromiseCapability").@promise.@then(@undefined, function(e) {
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000422 if (teeState.closedOrErrored)
423 return;
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000424 @readableStreamDefaultControllerError(branch1.@readableStreamController, e);
425 @readableStreamDefaultControllerError(branch2.@readableStreamController, e);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000426 teeState.closedOrErrored = true;
youenn@apple.coma40c11c2021-04-08 18:37:33 +0000427 if (!teeState.canceled1 || !teeState.canceled2)
428 teeState.cancelPromiseCapability.@resolve.@call();
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000429 });
430
431 // Additional fields compared to the spec, as they are needed within pull/cancel functions.
432 teeState.branch1 = branch1;
433 teeState.branch2 = branch2;
434
435 return [branch1, branch2];
436}
437
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000438function readableStreamTeePullFunction(teeState, reader, shouldClone)
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000439{
calvaris@igalia.com3e2838f2015-11-10 15:45:21 +0000440 "use strict";
441
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000442 return function() {
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000443 @Promise.prototype.@then.@call(@readableStreamDefaultReaderRead(reader), function(result) {
calvaris@igalia.com54525e32015-11-16 10:21:37 +0000444 @assert(@isObject(result));
445 @assert(typeof result.done === "boolean");
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000446 if (result.done && !teeState.closedOrErrored) {
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000447 if (!teeState.canceled1)
448 @readableStreamDefaultControllerClose(teeState.branch1.@readableStreamController);
449 if (!teeState.canceled2)
450 @readableStreamDefaultControllerClose(teeState.branch2.@readableStreamController);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000451 teeState.closedOrErrored = true;
youenn@apple.coma40c11c2021-04-08 18:37:33 +0000452 if (!teeState.canceled1 || !teeState.canceled2)
453 teeState.cancelPromiseCapability.@resolve.@call();
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000454 }
455 if (teeState.closedOrErrored)
456 return;
commit-queue@webkit.org51aa0602016-08-29 10:52:42 +0000457 if (!teeState.canceled1)
commit-queue@webkit.org5299bac2016-10-28 06:27:29 +0000458 @readableStreamDefaultControllerEnqueue(teeState.branch1.@readableStreamController, result.value);
commit-queue@webkit.org51aa0602016-08-29 10:52:42 +0000459 if (!teeState.canceled2)
ysuzuki@apple.com38296f52021-07-09 00:38:41 +0000460 @readableStreamDefaultControllerEnqueue(teeState.branch2.@readableStreamController, shouldClone ? @structuredCloneForStream(result.value) : result.value);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000461 });
462 }
463}
464
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000465function readableStreamTeeBranch1CancelFunction(teeState, stream)
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000466{
calvaris@igalia.com3e2838f2015-11-10 15:45:21 +0000467 "use strict";
468
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000469 return function(r) {
470 teeState.canceled1 = true;
471 teeState.reason1 = r;
472 if (teeState.canceled2) {
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000473 @readableStreamCancel(stream, [teeState.reason1, teeState.reason2]).@then(
youenn.fablet@crf.canon.frc4d811f2015-12-14 17:27:27 +0000474 teeState.cancelPromiseCapability.@resolve,
475 teeState.cancelPromiseCapability.@reject);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000476 }
calvaris@igalia.com3b73dbc2015-11-03 14:52:04 +0000477 return teeState.cancelPromiseCapability.@promise;
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000478 }
479}
480
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000481function readableStreamTeeBranch2CancelFunction(teeState, stream)
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000482{
calvaris@igalia.com3e2838f2015-11-10 15:45:21 +0000483 "use strict";
484
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000485 return function(r) {
486 teeState.canceled2 = true;
487 teeState.reason2 = r;
488 if (teeState.canceled1) {
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000489 @readableStreamCancel(stream, [teeState.reason1, teeState.reason2]).@then(
youenn.fablet@crf.canon.frc4d811f2015-12-14 17:27:27 +0000490 teeState.cancelPromiseCapability.@resolve,
491 teeState.cancelPromiseCapability.@reject);
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000492 }
calvaris@igalia.com3b73dbc2015-11-03 14:52:04 +0000493 return teeState.cancelPromiseCapability.@promise;
youenn.fablet@crf.canon.fr7e822dd2015-10-19 10:09:07 +0000494 }
youenn.fablet@crf.canon.fr6ebc90f2015-10-01 12:30:43 +0000495}
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000496
497function isReadableStream(stream)
498{
499 "use strict";
500
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000501 // Spec tells to return true only if stream has a readableStreamController internal slot.
502 // However, since it is a private slot, it cannot be checked using hasOwnProperty().
503 // Therefore, readableStreamController is initialized with null value.
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000504 return @isObject(stream) && @getByIdDirectPrivate(stream, "readableStreamController") !== @undefined;
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000505}
506
commit-queue@webkit.orgba16f552016-07-27 10:40:17 +0000507function isReadableStreamDefaultReader(reader)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000508{
509 "use strict";
510
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000511 // Spec tells to return true only if reader has a readRequests internal slot.
512 // However, since it is a private slot, it cannot be checked using hasOwnProperty().
513 // Since readRequests is initialized with an empty array, the following test is ok.
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000514 return @isObject(reader) && !!@getByIdDirectPrivate(reader, "readRequests");
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000515}
516
commit-queue@webkit.orgd76af4e2016-07-28 15:43:42 +0000517function isReadableStreamDefaultController(controller)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000518{
519 "use strict";
520
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000521 // Spec tells to return true only if controller has an underlyingSource internal slot.
522 // However, since it is a private slot, it cannot be checked using hasOwnProperty().
523 // underlyingSource is obtained in ReadableStream constructor: if undefined, it is set
524 // to an empty object. Therefore, following test is ok.
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000525 return @isObject(controller) && !!@getByIdDirectPrivate(controller, "underlyingSource");
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000526}
527
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000528function readableStreamError(stream, error)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000529{
530 "use strict";
531
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000532 @assert(@isReadableStream(stream));
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000533 @assert(@getByIdDirectPrivate(stream, "state") === @streamReadable);
534 @putByIdDirectPrivate(stream, "state", @streamErrored);
535 @putByIdDirectPrivate(stream, "storedError", error);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000536
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000537 if (!@getByIdDirectPrivate(stream, "reader"))
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000538 return;
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000539
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000540 const reader = @getByIdDirectPrivate(stream, "reader");
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000541
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000542 if (@isReadableStreamDefaultReader(reader)) {
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000543 const requests = @getByIdDirectPrivate(reader, "readRequests");
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000544 @putByIdDirectPrivate(reader, "readRequests", []);
youenn@apple.com9cb19502020-08-19 15:02:50 +0000545 for (let index = 0, length = requests.length; index < length; ++index)
546 @rejectPromise(requests[index], error);
commit-queue@webkit.org2c90ad32017-05-11 18:32:25 +0000547 } else {
548 @assert(@isReadableStreamBYOBReader(reader));
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000549 const requests = @getByIdDirectPrivate(reader, "readIntoRequests");
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000550 @putByIdDirectPrivate(reader, "readIntoRequests", []);
youenn@apple.com9cb19502020-08-19 15:02:50 +0000551 for (let index = 0, length = requests.length; index < length; ++index)
552 @rejectPromise(requests[index], error);
commit-queue@webkit.org2c90ad32017-05-11 18:32:25 +0000553 }
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000554
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000555 @getByIdDirectPrivate(reader, "closedPromiseCapability").@reject.@call(@undefined, error);
ysuzuki@apple.com48d4e532019-09-05 01:23:46 +0000556 const promise = @getByIdDirectPrivate(reader, "closedPromiseCapability").@promise;
youenn@apple.com48835572020-08-18 08:45:09 +0000557 @markPromiseAsHandled(promise);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000558}
559
youenn@apple.comac36bf62020-08-27 10:00:20 +0000560function readableStreamDefaultControllerShouldCallPull(controller)
561{
562 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
563
564 if (!@readableStreamDefaultControllerCanCloseOrEnqueue(controller))
565 return false;
566 if (!@getByIdDirectPrivate(controller, "started"))
567 return false;
568 if ((!@isReadableStreamLocked(stream) || !@getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests").length) && @readableStreamDefaultControllerGetDesiredSize(controller) <= 0)
569 return false;
570 const desiredSize = @readableStreamDefaultControllerGetDesiredSize(controller);
571 @assert(desiredSize !== null);
572 return desiredSize > 0;
573}
574
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000575function readableStreamDefaultControllerCallPullIfNeeded(controller)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000576{
577 "use strict";
578
youenn@apple.comac36bf62020-08-27 10:00:20 +0000579 // FIXME: use @readableStreamDefaultControllerShouldCallPull
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000580 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000581
romain.bellessort@crf.canon.frfdb9ad22017-10-09 12:53:11 +0000582 if (!@readableStreamDefaultControllerCanCloseOrEnqueue(controller))
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000583 return;
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000584 if (!@getByIdDirectPrivate(controller, "started"))
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000585 return;
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000586 if ((!@isReadableStreamLocked(stream) || !@getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests").length) && @readableStreamDefaultControllerGetDesiredSize(controller) <= 0)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000587 return;
commit-queue@webkit.orgba16f552016-07-27 10:40:17 +0000588
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000589 if (@getByIdDirectPrivate(controller, "pulling")) {
590 @putByIdDirectPrivate(controller, "pullAgain", true);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000591 return;
592 }
593
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000594 @assert(!@getByIdDirectPrivate(controller, "pullAgain"));
595 @putByIdDirectPrivate(controller, "pulling", true);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000596
youenn@apple.com81f51e32020-06-17 08:55:55 +0000597 @getByIdDirectPrivate(controller, "pullAlgorithm").@call(@undefined).@then(function() {
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000598 @putByIdDirectPrivate(controller, "pulling", false);
599 if (@getByIdDirectPrivate(controller, "pullAgain")) {
600 @putByIdDirectPrivate(controller, "pullAgain", false);
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000601 @readableStreamDefaultControllerCallPullIfNeeded(controller);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000602 }
603 }, function(error) {
youenn@apple.com525b5862018-05-15 05:35:25 +0000604 @readableStreamDefaultControllerError(controller, error);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000605 });
606}
607
608function isReadableStreamLocked(stream)
609{
610 "use strict";
611
calvaris@igalia.com54525e32015-11-16 10:21:37 +0000612 @assert(@isReadableStream(stream));
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000613 return !!@getByIdDirectPrivate(stream, "reader");
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000614}
615
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000616function readableStreamDefaultControllerGetDesiredSize(controller)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000617{
618 "use strict";
619
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000620 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
621 const state = @getByIdDirectPrivate(stream, "state");
commit-queue@webkit.org5c4e4ad2017-05-18 12:56:46 +0000622
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000623 if (state === @streamErrored)
624 return null;
625 if (state === @streamClosed)
626 return 0;
commit-queue@webkit.org5c4e4ad2017-05-18 12:56:46 +0000627
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000628 return @getByIdDirectPrivate(controller, "strategy").highWaterMark - @getByIdDirectPrivate(controller, "queue").size;
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000629}
630
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000631
632function readableStreamReaderGenericCancel(reader, reason)
633{
634 "use strict";
635
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000636 const stream = @getByIdDirectPrivate(reader, "ownerReadableStream");
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000637 @assert(!!stream);
638 return @readableStreamCancel(stream, reason);
639}
640
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000641function readableStreamCancel(stream, reason)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000642{
643 "use strict";
644
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000645 @putByIdDirectPrivate(stream, "disturbed", true);
646 const state = @getByIdDirectPrivate(stream, "state");
647 if (state === @streamClosed)
calvaris@igalia.comcf5df702015-11-05 14:01:13 +0000648 return @Promise.@resolve();
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000649 if (state === @streamErrored)
650 return @Promise.@reject(@getByIdDirectPrivate(stream, "storedError"));
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000651 @readableStreamClose(stream);
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000652 return @getByIdDirectPrivate(stream, "readableStreamController").@cancel(@getByIdDirectPrivate(stream, "readableStreamController"), reason).@then(function() { });
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000653}
654
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000655function readableStreamDefaultControllerCancel(controller, reason)
656{
657 "use strict";
658
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000659 @putByIdDirectPrivate(controller, "queue", @newQueue());
youenn@apple.com81f51e32020-06-17 08:55:55 +0000660 return @getByIdDirectPrivate(controller, "cancelAlgorithm").@call(@undefined, reason);
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000661}
662
663function readableStreamDefaultControllerPull(controller)
664{
665 "use strict";
666
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000667 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
668 if (@getByIdDirectPrivate(controller, "queue").content.length) {
669 const chunk = @dequeueValue(@getByIdDirectPrivate(controller, "queue"));
670 if (@getByIdDirectPrivate(controller, "closeRequested") && @getByIdDirectPrivate(controller, "queue").content.length === 0)
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000671 @readableStreamClose(stream);
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000672 else
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000673 @readableStreamDefaultControllerCallPullIfNeeded(controller);
youenn@apple.com9cb19502020-08-19 15:02:50 +0000674
675 return @createFulfilledPromise({ value: chunk, done: false });
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000676 }
677 const pendingPromise = @readableStreamAddReadRequest(stream);
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000678 @readableStreamDefaultControllerCallPullIfNeeded(controller);
commit-queue@webkit.org66abf1f2016-09-28 09:17:57 +0000679 return pendingPromise;
680}
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000681
682function readableStreamDefaultControllerClose(controller)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000683{
684 "use strict";
685
romain.bellessort@crf.canon.frfdb9ad22017-10-09 12:53:11 +0000686 @assert(@readableStreamDefaultControllerCanCloseOrEnqueue(controller));
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000687 @putByIdDirectPrivate(controller, "closeRequested", true);
688 if (@getByIdDirectPrivate(controller, "queue").content.length === 0)
689 @readableStreamClose(@getByIdDirectPrivate(controller, "controlledReadableStream"));
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000690}
691
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000692function readableStreamClose(stream)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000693{
694 "use strict";
695
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000696 @assert(@getByIdDirectPrivate(stream, "state") === @streamReadable);
697 @putByIdDirectPrivate(stream, "state", @streamClosed);
698 const reader = @getByIdDirectPrivate(stream, "reader");
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000699
700 if (!reader)
commit-queue@webkit.orgba16f552016-07-27 10:40:17 +0000701 return;
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000702
703 if (@isReadableStreamDefaultReader(reader)) {
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000704 const requests = @getByIdDirectPrivate(reader, "readRequests");
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000705 @putByIdDirectPrivate(reader, "readRequests", []);
youenn@apple.com9cb19502020-08-19 15:02:50 +0000706 for (let index = 0, length = requests.length; index < length; ++index)
707 @fulfillPromise(requests[index], { value: @undefined, done: true });
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000708 }
709
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000710 @getByIdDirectPrivate(reader, "closedPromiseCapability").@resolve.@call();
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000711}
712
commit-queue@webkit.orgc7004c62017-02-07 09:00:10 +0000713function readableStreamFulfillReadRequest(stream, chunk, done)
714{
715 "use strict";
youenn@apple.com9cb19502020-08-19 15:02:50 +0000716 const readRequest = @getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests").@shift();
717 @fulfillPromise(readRequest, { value: chunk, done: done });
commit-queue@webkit.orgc7004c62017-02-07 09:00:10 +0000718}
719
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000720function readableStreamDefaultControllerEnqueue(controller, chunk)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000721{
722 "use strict";
723
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000724 const stream = @getByIdDirectPrivate(controller, "controlledReadableStream");
romain.bellessort@crf.canon.frfdb9ad22017-10-09 12:53:11 +0000725 @assert(@readableStreamDefaultControllerCanCloseOrEnqueue(controller));
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000726
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000727 if (@isReadableStreamLocked(stream) && @getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests").length) {
commit-queue@webkit.orgc7004c62017-02-07 09:00:10 +0000728 @readableStreamFulfillReadRequest(stream, chunk, false);
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000729 @readableStreamDefaultControllerCallPullIfNeeded(controller);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000730 return;
731 }
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000732
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000733 try {
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000734 let chunkSize = 1;
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000735 if (@getByIdDirectPrivate(controller, "strategy").size !== @undefined)
736 chunkSize = @getByIdDirectPrivate(controller, "strategy").size(chunk);
737 @enqueueValueWithSize(@getByIdDirectPrivate(controller, "queue"), chunk, chunkSize);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000738 }
739 catch(error) {
youenn@apple.com525b5862018-05-15 05:35:25 +0000740 @readableStreamDefaultControllerError(controller, error);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000741 throw error;
742 }
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000743 @readableStreamDefaultControllerCallPullIfNeeded(controller);
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000744}
745
commit-queue@webkit.orgfcaa5122016-10-05 16:46:19 +0000746function readableStreamDefaultReaderRead(reader)
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000747{
748 "use strict";
749
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000750 const stream = @getByIdDirectPrivate(reader, "ownerReadableStream");
calvaris@igalia.com54525e32015-11-16 10:21:37 +0000751 @assert(!!stream);
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000752 const state = @getByIdDirectPrivate(stream, "state");
commit-queue@webkit.orgf4555b722016-07-13 16:08:51 +0000753
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000754 @putByIdDirectPrivate(stream, "disturbed", true);
755 if (state === @streamClosed)
youenn@apple.com9cb19502020-08-19 15:02:50 +0000756 return @createFulfilledPromise({ value: @undefined, done: true });
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000757 if (state === @streamErrored)
758 return @Promise.@reject(@getByIdDirectPrivate(stream, "storedError"));
759 @assert(state === @streamReadable);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000760
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000761 return @getByIdDirectPrivate(stream, "readableStreamController").@pull(@getByIdDirectPrivate(stream, "readableStreamController"));
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000762}
763
764function readableStreamAddReadRequest(stream)
765{
766 "use strict";
767
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000768 @assert(@isReadableStreamDefaultReader(@getByIdDirectPrivate(stream, "reader")));
769 @assert(@getByIdDirectPrivate(stream, "state") == @streamReadable);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000770
youenn@apple.com9cb19502020-08-19 15:02:50 +0000771 const readRequest = @newPromise();
shvaikalesh@gmail.comf230b5e2020-10-14 21:48:50 +0000772 @arrayPush(@getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests"), readRequest);
commit-queue@webkit.orgc740d212016-09-01 14:14:05 +0000773
youenn@apple.com9cb19502020-08-19 15:02:50 +0000774 return readRequest;
youenn.fablet@crf.canon.frc8f54022015-10-06 06:20:58 +0000775}
calvaris@igalia.com26c50782015-11-19 09:21:47 +0000776
777function isReadableStreamDisturbed(stream)
778{
779 "use strict";
780
781 @assert(@isReadableStream(stream));
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000782 return @getByIdDirectPrivate(stream, "disturbed");
calvaris@igalia.com26c50782015-11-19 09:21:47 +0000783}
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000784
785function readableStreamReaderGenericRelease(reader)
786{
787 "use strict";
788
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000789 @assert(!!@getByIdDirectPrivate(reader, "ownerReadableStream"));
790 @assert(@getByIdDirectPrivate(@getByIdDirectPrivate(reader, "ownerReadableStream"), "reader") === reader);
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000791
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000792 if (@getByIdDirectPrivate(@getByIdDirectPrivate(reader, "ownerReadableStream"), "state") === @streamReadable)
ysuzuki@apple.comba74bbe2019-03-04 18:56:22 +0000793 @getByIdDirectPrivate(reader, "closedPromiseCapability").@reject.@call(@undefined, @makeTypeError("releasing lock of reader whose stream is still in readable state"));
commit-queue@webkit.org835538c2017-05-16 12:47:22 +0000794 else
ysuzuki@apple.comba74bbe2019-03-04 18:56:22 +0000795 @putByIdDirectPrivate(reader, "closedPromiseCapability", { @promise: @newHandledRejectedPromise(@makeTypeError("reader released lock")) });
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000796
ysuzuki@apple.com48d4e532019-09-05 01:23:46 +0000797 const promise = @getByIdDirectPrivate(reader, "closedPromiseCapability").@promise;
youenn@apple.com48835572020-08-18 08:45:09 +0000798 @markPromiseAsHandled(promise);
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000799 @putByIdDirectPrivate(@getByIdDirectPrivate(reader, "ownerReadableStream"), "reader", @undefined);
800 @putByIdDirectPrivate(reader, "ownerReadableStream", @undefined);
commit-queue@webkit.org3f33e862016-10-07 15:10:46 +0000801}
romain.bellessort@crf.canon.frfdb9ad22017-10-09 12:53:11 +0000802
803function readableStreamDefaultControllerCanCloseOrEnqueue(controller)
804{
805 "use strict";
806
utatane.tea@gmail.comae5c2f42018-04-13 17:01:40 +0000807 return !@getByIdDirectPrivate(controller, "closeRequested") && @getByIdDirectPrivate(@getByIdDirectPrivate(controller, "controlledReadableStream"), "state") === @streamReadable;
romain.bellessort@crf.canon.frfdb9ad22017-10-09 12:53:11 +0000808}