Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: Source/core/streams/ReadableStream2.js

Issue 1167343002: Add methods for creating V8 extras-based ReadableStreams from C++ (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Remove C++ queuing strategies Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 (function(global, exports) {
2 'use strict';
3
4 // V8 "Imports":
5 // - %CreatePrivateOwnSymbol
6 // - %_CallFunction
7 // - %AddNamedProperty
8 // - %HasOwnProperty
9 // - $promiseThen, $promiseCreate, $promiseResolve, $promiseReject
10
11 const readableStreamClosedPromise = %CreatePrivateOwnSymbol('[[closedPromise ]]');
12 const readableStreamCloseRequested = %CreatePrivateOwnSymbol('[[closeRequest ed]]');
13 const readableStreamController = %CreatePrivateOwnSymbol('[[controller]]');
14 const readableStreamPullAgain = %CreatePrivateOwnSymbol('[[pullAgain]]');
15 const readableStreamPulling = %CreatePrivateOwnSymbol('[[pulling]]');
16 const readableStreamQueue = %CreatePrivateOwnSymbol('[[queue]]');
17 const readableStreamQueueSize = %CreatePrivateOwnSymbol('[[queue]] total siz e');
18 const readableStreamReader = %CreatePrivateOwnSymbol('[[reader]]');
19 const readableStreamStarted = %CreatePrivateOwnSymbol('[[started]]');
20 const readableStreamState = %CreatePrivateOwnSymbol('[[state]]');
21 const readableStreamStoredError = %CreatePrivateOwnSymbol('[[storedError]]') ;
22 const readableStreamStrategySize = %CreatePrivateOwnSymbol('[[strategySize]] ');
23 const readableStreamStrategyHWM = %CreatePrivateOwnSymbol('[[strategyHWM]]') ;
24 const readableStreamUnderlyingSource = %CreatePrivateOwnSymbol('[[underlying Source]]');
25
26 const readableStreamControllerControlledReadableStream = %CreatePrivateOwnSy mbol('[[controlledReadableStream]]');
27
28 const readableStreamReaderClosedPromise = %CreatePrivateOwnSymbol('[[closedP romise]]');
29 const readableStreamReaderOwnerReadableStream = %CreatePrivateOwnSymbol('[[o wnerReadableStream]]');
30 const readableStreamReaderReadRequests = %CreatePrivateOwnSymbol('[[readRequ ests]]');
31 const readableStreamReaderState = %CreatePrivateOwnSymbol('[[state]]');
32 const readableStreamReaderStoredError = %CreatePrivateOwnSymbol('[[storedErr or]]');
33
34 const createWithExternalControllerSentinel = %CreatePrivateOwnSymbol(
35 'flag for UA-controlled ReadableStreams to pass');
36
37 const undefined = void 0;
38 const DONT_ENUM = 2;
39
40 const STATE_READABLE = 0;
41 const STATE_CLOSED = 1;
42 const STATE_ERRORED = 2;
43
44 const TypeError = global.TypeError;
45 const RangeError = global.RangeError;
46 const Promise = global.Promise;
47
48 const Number = global.Number;
49 const Number_isNaN = global.Number.isNaN;
50 const Number_isFinite = global.Number.isFinite;
51
52 // TODO(domenic): update to use InternalPackedArray once yangguo gives us ac cess in extras
53 const InternalPackedArray = global.Array;
54
55 function thenPromise(promise, f, r) {
56 return %_CallFunction(promise, f, r, $promiseThen);
57 }
58
59 // Manually create "bound" versions since Function.prototype.bind is slow.
60 const Promise_resolve = (function() {
61 const unbound = Promise.resolve;
62 return function(x) {
63 return %_CallFunction(Promise, x, unbound);
64 };
65 })();
66
67 const Promise_reject = (function() {
68 const unbound = Promise.reject;
69 return function(r) {
70 return %_CallFunction(Promise, r, unbound);
71 };
72 })();
73
74 class ReadableStream {
75 constructor(underlyingSource, strategy) {
76 if (underlyingSource === undefined) {
77 underlyingSource = {};
78 }
79 if (strategy === undefined) {
80 strategy = {};
81 }
82 const size = strategy.size;
83 let highWaterMark = strategy.highWaterMark;
84 if (highWaterMark === undefined) {
85 highWaterMark = 1;
86 }
87
88 const normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
89
90 this[readableStreamUnderlyingSource] = underlyingSource;
91
92 this[readableStreamQueue] = new InternalPackedArray();
93 this[readableStreamQueueSize] = 0;
94
95 // TODO(domenic) consolidate booleans into a bit field?
96 // TODO(domenic) use integers for state? (or put in bit field?)
97 this[readableStreamState] = STATE_READABLE;
98 this[readableStreamStarted] = false;
99 this[readableStreamCloseRequested] = false;
100 this[readableStreamPulling] = false;
101 this[readableStreamPullAgain] = false;
102 this[readableStreamReader] = undefined;
103
104 this[readableStreamStoredError] = undefined;
105 this[readableStreamStrategySize] = normalizedStrategy.size;
106 this[readableStreamStrategyHWM] = normalizedStrategy.highWaterMark;
107
108 // Avoid allocating a controller if the stream is going to be contro lled externally (i.e. from C++) anyway.
109 // All calls to underlyingSource methods will disregard their contro ller argument in such situations
110 // (but see below).
111 const controller = arguments[2] === createWithExternalControllerSent inel ?
112 null :
113 new ReadableStreamController(this);
114 this[readableStreamController] = controller;
115
116 // We need to pass ourself to the underlyingSource start method for externally-controlled streams. We
117 // use the now-useless controller argument to do so.
118 const argToStart = arguments[2] === createWithExternalControllerSent inel ? this : controller;
119
120 const that = this;
121 const startResult = CallOrNoop(underlyingSource, 'start', argToStart , 'underlyingSource.start');
122 thenPromise(Promise_resolve(startResult),
123 function() {
124 that[readableStreamStarted] = true;
125 RequestReadableStreamPull(that);
126 },
127 function(r) {
128 if (that[readableStreamState] === STATE_READABLE) {
129 return ErrorReadableStream(that, r);
130 }
131 }
132 );
133 }
134
135 cancel(reason) {
136 if (IsReadableStream(this) === false) {
137 return Promise_reject(new TypeError(
138 'ReadableStream.prototype.cancel can only be used on a Reada bleStream'));
139 }
140
141 if (IsReadableStreamLocked(this) === true) {
142 return Promise_reject(new TypeError(
143 'Cannot cancel a stream that already has a reader'));
144 }
145
146 return CancelReadableStream(this, reason);
147 }
148
149 getReader() {
150 if (IsReadableStream(this) === false) {
151 throw new TypeError('ReadableStream.prototype.getReader can only be used on a ReadableStream');
152 }
153
154 return AcquireReadableStreamReader(this);
155 }
156
157 tee() {
158 if (IsReadableStream(this) === false) {
159 throw new TypeError('ReadableStream.prototype.tee can only be us ed on a ReadableStream');
160 }
161
162 return TeeReadableStream(this);
163 }
164 }
165
166 class ReadableStreamController {
167 constructor(stream) {
168 if (IsReadableStream(stream) === false) {
169 throw new TypeError('ReadableStreamController can only be constr ucted with a ReadableStream instance');
170 }
171
172 if (stream[readableStreamController] !== undefined) {
173 throw new TypeError(
174 'ReadableStreamController instances can only be created by t he ReadableStream constructor');
175 }
176
177 this[readableStreamControllerControlledReadableStream] = stream;
178 }
179
180 get desiredSize() {
181 if (IsReadableStreamController(this) === false) {
182 throw new TypeError(
183 'ReadableStreamController.prototype.desiredSize can only be used on a ReadableStreamController');
184 }
185
186 return GetReadableStreamDesiredSize(this[readableStreamControllerCon trolledReadableStream]);
187 }
188
189 close() {
190 if (IsReadableStreamController(this) === false) {
191 throw new TypeError(
192 'ReadableStreamController.prototype.close can only be used o n a ReadableStreamController');
193 }
194
195 const stream = this[readableStreamControllerControlledReadableStream ];
196
197 if (stream[readableStreamCloseRequested] === true) {
198 throw new TypeError('The stream has already been closed; do not close it again!');
199 }
200 if (stream[readableStreamState] === STATE_ERRORED) {
201 throw new TypeError('The stream is in an errored state and canno t be closed');
202 }
203
204 return CloseReadableStream(stream);
205 }
206
207 enqueue(chunk) {
208 if (IsReadableStreamController(this) === false) {
209 throw new TypeError(
210 'ReadableStreamController.prototype.enqueue can only be used on a ReadableStreamController');
211 }
212
213 const stream = this[readableStreamControllerControlledReadableStream ];
214
215 if (stream[readableStreamState] === STATE_ERRORED) {
216 throw stream[readableStreamStoredError];
217 }
218
219 if (stream[readableStreamCloseRequested] === true) {
220 throw new TypeError('stream is closed or draining');
221 }
222
223 return EnqueueInReadableStream(stream, chunk);
224 }
225
226 error(e) {
227 if (IsReadableStreamController(this) === false) {
228 throw new TypeError(
229 'ReadableStreamController.prototype.error can only be used o n a ReadableStreamController');
230 }
231
232 const stream = this[readableStreamControllerControlledReadableStream ];
233
234 const state = stream[readableStreamState];
235 if (state !== STATE_READABLE) {
236 throw new TypeError(`The stream is ${state} and so cannot be err ored`);
237 }
238
239 return ErrorReadableStream(stream, e);
240 }
241 }
242
243 class ReadableStreamReader {
244 constructor(stream) {
245 if (IsReadableStream(stream) === false) {
246 throw new TypeError('ReadableStreamReader can only be constructed with a ReadableStream instance');
247 }
248 if (IsReadableStreamLocked(stream) === true) {
249 throw new TypeError('This stream has already been locked for exclu sive reading by another reader');
250 }
251
252 stream[readableStreamReader] = this;
253 this[readableStreamReaderOwnerReadableStream] = stream;
254
255 // TODO(domenic): use integers for state?
256 this[readableStreamReaderState] = STATE_READABLE;
257 this[readableStreamReaderStoredError] = undefined;
258 this[readableStreamReaderReadRequests] = new InternalPackedArray();
259 this[readableStreamReaderClosedPromise] = $promiseCreate();
260
261 const streamState = stream[readableStreamState];
262 if (streamState === STATE_CLOSED || streamState === STATE_ERRORED) {
263 ReleaseReadableStreamReader(this);
264 }
265 }
266
267 get closed() {
268 if (IsReadableStreamReader(this) === false) {
269 return Promise_reject(
270 new TypeError('ReadableStreamReader.prototype.closed can onl y be used on a ReadableStreamReader'));
271 }
272
273 return this[readableStreamReaderClosedPromise];
274 }
275
276 cancel(reason) {
277 if (IsReadableStreamReader(this) === false) {
278 return Promise_reject(
279 new TypeError('ReadableStreamReader.prototype.cancel can onl y be used on a ReadableStreamReader'));
280 }
281
282 const state = this[readableStreamReaderState];
283 if (state === STATE_CLOSED) {
284 return Promise_resolve(undefined);
285 }
286
287 if (state === STATE_ERRORED) {
288 return Promise_reject(this[readableStreamReaderStoredError]);
289 }
290
291 return CancelReadableStream(this[readableStreamReaderOwnerReadableSt ream], reason);
292 }
293
294 read() {
295 if (IsReadableStreamReader(this) === false) {
296 return Promise_reject(
297 new TypeError('ReadableStreamReader.prototype.read can only be used on a ReadableStreamReader'));
298 }
299
300 return ReadFromReadableStreamReader(this);
301 }
302
303 releaseLock() {
304 if (IsReadableStreamReader(this) === false) {
305 throw new TypeError(
306 'ReadableStreamReader.prototype.releaseLock can only be used on a ReadableStreamReader');
307 }
308
309 if (this[readableStreamReaderOwnerReadableStream] === undefined) {
310 return undefined;
311 }
312
313 if (this[readableStreamReaderReadRequests].length > 0) {
314 throw new TypeError(
315 'Tried to release a reader lock when that reader has pending read() calls un-settled');
316 }
317
318 return ReleaseReadableStreamReader(this);
319 }
320 }
321
322 //
323 // Readable stream abstract operations
324 //
325
326 function AcquireReadableStreamReader(stream) {
327 return new ReadableStreamReader(stream);
328 }
329
330 function CancelReadableStream(stream, reason) {
331 const state = stream[readableStreamState];
332 if (state === STATE_CLOSED) {
333 return Promise_resolve(undefined);
334 }
335 if (state === STATE_ERRORED) {
336 return Promise_reject(stream[readableStreamStoredError]);
337 }
338
339 stream[readableStreamQueue] = new InternalPackedArray();
340 FinishClosingReadableStream(stream);
341
342 const underlyingSource = stream[readableStreamUnderlyingSource];
343 const sourceCancelPromise = PromiseCallOrNoop(underlyingSource, 'cancel' , reason, 'underlyingSource.cancel');
344 return thenPromise(sourceCancelPromise, function() { return undefined; } );
345 }
346
347 function CloseReadableStream(stream) {
348 if (stream[readableStreamState] === STATE_CLOSED) {
349 return undefined;
350 }
351
352 stream[readableStreamCloseRequested] = true;
353
354 if (stream[readableStreamQueue].length === 0) {
355 return FinishClosingReadableStream(stream);
356 }
357 }
358
359
360 function EnqueueInReadableStream(stream, chunk) {
361 if (stream[readableStreamState] === STATE_CLOSED) {
362 return undefined;
363 }
364
365 if (IsReadableStreamLocked(stream) === true &&
366 stream[readableStreamReader][readableStreamReaderReadRequests].lengt h > 0) {
367 const readRequest = stream[readableStreamReader][readableStreamReade rReadRequests].shift();
368 $promiseResolve(readRequest, CreateIterResultObject(chunk, false));
369 } else {
370 let chunkSize = 1;
371
372 const strategySize = stream[readableStreamStrategySize];
373 if (strategySize !== undefined) {
374 try {
375 chunkSize = strategySize(chunk);
376 } catch (chunkSizeE) {
377 ErrorReadableStream(stream, chunkSizeE);
378 throw chunkSizeE;
379 }
380 }
381
382 try {
383 EnqueueValueWithSize(stream, chunk, chunkSize);
384 } catch (enqueueE) {
385 ErrorReadableStream(stream, enqueueE);
386 throw enqueueE;
387 }
388 }
389
390 RequestReadableStreamPull(stream);
391 }
392
393 function ErrorReadableStream(stream, e) {
394 stream[readableStreamQueue] = new InternalPackedArray();
395 stream[readableStreamStoredError] = e;
396 stream[readableStreamState] = STATE_ERRORED;
397
398 if (IsReadableStreamLocked(stream) === true) {
399 return ReleaseReadableStreamReader(stream[readableStreamReader]);
400 }
401 }
402
403 function FinishClosingReadableStream(stream) {
404 stream[readableStreamState] = STATE_CLOSED;
405
406 if (IsReadableStreamLocked(stream) === true) {
407 return ReleaseReadableStreamReader(stream[readableStreamReader]);
408 }
409 }
410
411 function GetReadableStreamDesiredSize(stream) {
412 const queueSize = GetTotalQueueSize(stream);
413 return stream[readableStreamStrategyHWM] - queueSize;
414 }
415
416 function IsReadableStream(x) {
417 return %HasOwnProperty(x, readableStreamUnderlyingSource);
418 }
419
420 function IsReadableStreamLocked(stream) {
421 return stream[readableStreamReader] !== undefined;
422 }
423
424 function IsReadableStreamController(x) {
425 return %HasOwnProperty(x, readableStreamControllerControlledReadableStre am);
426 }
427
428 function IsReadableStreamReader(x) {
429 return %HasOwnProperty(x, readableStreamReaderOwnerReadableStream);
430 }
431
432 function ReadFromReadableStreamReader(reader) {
433 const state = reader[readableStreamReaderState];
434 if (state === STATE_CLOSED) {
435 return Promise_resolve(CreateIterResultObject(undefined, true));
436 }
437
438 if (state === STATE_ERRORED) {
439 return Promise_reject(reader[readableStreamReaderStoredError]);
440 }
441
442 const ownerReadableStream = reader[readableStreamReaderOwnerReadableStre am];
443 const queue = ownerReadableStream[readableStreamQueue];
444 if (queue.length > 0) {
445 const chunk = DequeueValue(ownerReadableStream);
446
447 if (ownerReadableStream[readableStreamCloseRequested] === true && qu eue.length === 0) {
448 FinishClosingReadableStream(ownerReadableStream);
449 } else {
450 RequestReadableStreamPull(ownerReadableStream);
451 }
452
453 return Promise_resolve(CreateIterResultObject(chunk, false));
454 } else {
455 const readRequest = $promiseCreate();
456
457 reader[readableStreamReaderReadRequests].push(readRequest);
458 RequestReadableStreamPull(ownerReadableStream);
459 return readRequest;
460 }
461 }
462
463 function ReleaseReadableStreamReader(reader) {
464 const ownerReadableStream = reader[readableStreamReaderOwnerReadableStre am];
465 if (ownerReadableStream[readableStreamState] === STATE_ERRORED) {
466 reader[readableStreamReaderState] = STATE_ERRORED;
467
468 const e = ownerReadableStream[readableStreamStoredError];
469 reader[readableStreamReaderStoredError] = e;
470 $promiseReject(reader[readableStreamReaderClosedPromise], e);
471
472 const readRequests = reader[readableStreamReaderReadRequests];
473 for (let i = 0; i < readRequests.length; ++i) {
474 $promiseReject(readRequests[i], e);
475 }
476 } else {
477 reader[readableStreamReaderState] = STATE_CLOSED;
478 $promiseResolve(reader[readableStreamReaderClosedPromise], undefined );
479
480 const readRequests = reader[readableStreamReaderReadRequests];
481 for (let i = 0; i < readRequests.length; ++i) {
482 $promiseResolve(readRequests[i], CreateIterResultObject(undefine d, true));
483 }
484 }
485
486 reader[readableStreamReaderReadRequests] = new InternalPackedArray();
487 ownerReadableStream[readableStreamReader] = undefined;
488 reader[readableStreamReaderOwnerReadableStream] = undefined;
489 }
490
491 function RequestReadableStreamPull(stream) {
492 const shouldPull = ShouldReadableStreamPull(stream);
493 if (shouldPull === false) {
494 return undefined;
495 }
496
497 if (stream[readableStreamPulling] === true) {
498 stream[readableStreamPullAgain] = true;
499 return undefined;
500 }
501
502 stream[readableStreamPulling] = true;
503
504 const underlyingSource = stream[readableStreamUnderlyingSource];
505 const controller = stream[readableStreamController];
506 const pullPromise = PromiseCallOrNoop(underlyingSource, 'pull', controll er, 'underlyingSource.pull');
507
508 thenPromise(pullPromise,
509 function() {
510 stream[readableStreamPulling] = false;
511
512 if (stream[readableStreamPullAgain] === true) {
513 stream[readableStreamPullAgain] = false;
514 return RequestReadableStreamPull(stream);
515 }
516 },
517 function(e) {
518 if (stream[readableStreamState] === STATE_READABLE) {
519 return ErrorReadableStream(stream, e);
520 }
521 }
522 );
523 }
524
525 function ShouldReadableStreamPull(stream) {
526 const state = stream[readableStreamState];
527 if (state === STATE_CLOSED || state === STATE_ERRORED) {
528 return false;
529 }
530
531 if (stream[readableStreamCloseRequested] === true) {
532 return false;
533 }
534
535 if (stream[readableStreamStarted] === false) {
536 return false;
537 }
538
539 if (IsReadableStreamLocked(stream) === true) {
540 const reader = stream[readableStreamReader];
541 const readRequests = reader[readableStreamReaderReadRequests];
542 if (readRequests.length > 0) {
543 return true;
544 }
545 }
546
547 const desiredSize = GetReadableStreamDesiredSize(stream);
548 if (desiredSize > 0) {
549 return true;
550 }
551
552 return false;
553 }
554
555 // Potential future optimization: use class instances for the underlying sou rces, so that we don't re-create
556 // closures every time.
557
558 function TeeReadableStream(stream) { // shouldClone argument from spec not s upported yet
559 const reader = AcquireReadableStreamReader(stream);
560
561 let closedOrErrored = false;
562 let canceled1 = false;
563 let canceled2 = false;
564 let reason1;
565 let reason2;
566 let promise = $promiseCreate();
567
568 const branch1 = new ReadableStream({
569 pull,
570 cancel: cancel1
571 });
572
573 const branch2 = new ReadableStream({
574 pull,
575 cancel: cancel2
576 });
577
578 thenPromise(reader[readableStreamReaderClosedPromise], undefined, functi on (r) {
579 if (closedOrErrored === true) {
580 return;
581 }
582
583 ErrorReadableStream(branch1, r);
584 ErrorReadableStream(branch2, r);
585 closedOrErrored = true;
586 });
587
588 return [branch1, branch2];
589
590
591 function pull() {
592 return thenPromise(ReadFromReadableStreamReader(reader), function (r esult) {
593 const value = result.value;
594 const done = result.done;
595
596 if (done === true && closedOrErrored === false) {
597 CloseReadableStream(branch1);
598 CloseReadableStream(branch2);
599 closedOrErrored = true;
600 }
601
602 if (closedOrErrored === true) {
603 return;
604 }
605
606 if (canceled1 === false) {
607 EnqueueInReadableStream(branch1, value);
608 }
609
610 if (canceled2 === false) {
611 EnqueueInReadableStream(branch2, value);
612 }
613 });
614 }
615
616 function cancel1(reason) {
617 canceled1 = true;
618 reason1 = reason;
619
620 if (canceled2 === true) {
621 const compositeReason = [reason1, reason2];
622 const cancelResult = CancelReadableStream(stream, compositeReaso n);
623 $promiseResolve(promise, cancelResult);
624 }
625
626 return promise;
627 }
628
629 function cancel2(reason) {
630 canceled2 = true;
631 reason2 = reason;
632
633 if (canceled1 === true) {
634 const compositeReason = [reason1, reason2];
635 const cancelResult = CancelReadableStream(stream, compositeReaso n);
636 $promiseResolve(promise, cancelResult);
637 }
638
639 return promise;
640 }
641 }
642
643 //
644 // Queue-with-sizes
645 // Modified from taking the queue (as in the spec) to taking the stream, so we can modify the queue size alongside.
646 //
647
648 function DequeueValue(stream) {
649 const result = stream[readableStreamQueue].shift();
650 stream[readableStreamQueueSize] -= result.size;
651 return result.value;
652 }
653
654 function EnqueueValueWithSize(stream, value, size) {
655 size = Number(size);
656 if (!Number_isFinite(size)) {
657 throw new RangeError('size must be a finite, non-NaN number.');
658 }
659
660 stream[readableStreamQueueSize] += size;
661 stream[readableStreamQueue].push({ value, size });
662 }
663
664 function GetTotalQueueSize(stream) {
665 return stream[readableStreamQueueSize];
666 }
667
668 //
669 // Other helpers
670 //
671
672 function ValidateAndNormalizeQueuingStrategy(size, highWaterMark) {
673 if (size !== undefined && typeof size !== 'function') {
674 throw new TypeError('size property of a queuing strategy must be a f unction');
675 }
676
677 highWaterMark = Number(highWaterMark);
678 if (Number_isNaN(highWaterMark)) {
679 throw new TypeError('highWaterMark property of a queuing strategy mu st be convertible to a non-NaN number');
680 }
681 if (highWaterMark < 0) {
682 throw new RangeError('highWaterMark property of a queuing strategy m ust be nonnegative');
683 }
684
685 return { size, highWaterMark };
686 }
687
688 function CallOrNoop(O, P, arg, nameForError) { // Modified from InvokeOrNoo p in spec
689 const method = O[P];
690 if (method === undefined) {
691 return undefined;
692 }
693 if (typeof method !== 'function') {
694 throw new TypeError(`${nameForError} must be a function or undefined `);
695 }
696
697 return %_CallFunction(O, arg, method);
698 }
699
700
701 function PromiseCallOrNoop(O, P, arg, nameForError) { // Modified from Promi seInvokeOrNoop in spec
702 let method;
703 try {
704 method = O[P];
705 } catch (methodE) {
706 return Promise_reject(methodE);
707 }
708
709 if (method === undefined) {
710 return Promise_resolve(undefined);
711 }
712
713 if (typeof method !== 'function') {
714 return Promise_reject(`${nameForError} must be a function or undefin ed`);
715 }
716
717 try {
718 return Promise_resolve(%_CallFunction(O, arg, method));
719 } catch (e) {
720 return Promise_reject(e);
721 }
722 }
723
724 function CreateIterResultObject(value, done) {
725 return { value, done };
726 }
727
728
729 //
730 // Additions to the global
731 //
732
733 %AddNamedProperty(global, 'ReadableStream', ReadableStream, DONT_ENUM);
734
735 //
736 // Exports for Blink to use
737 //
738
739 exports.ReadableStream = ReadableStream;
740 exports.createWithExternalControllerSentinel = createWithExternalControllerS entinel;
741 exports.ErrorReadableStream = ErrorReadableStream;
742 exports.EnqueueInReadableStream = EnqueueInReadableStream;
743 exports.CloseReadableStream = CloseReadableStream;
744 exports.GetReadableStreamDesiredSize = GetReadableStreamDesiredSize;
745 exports.IsReadableStreamLocked = IsReadableStreamLocked;
746
747 exports.$readAllInternal = function(stream) {
748 if (IsReadableStreamLocked(stream) === true) {
749 throw new TypeError("Cannot read the queue of a locked stream");
750 }
751
752 // Make sure to lock while doing anything that could call author code (e .g. calling pull).
753 const reader = AcquireReadableStreamReader(stream);
754
755 RequestReadableStreamPull();
756
757 const result = new InternalPackedArray();
758
759 const queue = stream[readableStreamQueue];
760 while (queue.length > 0) {
761 result.push(DequeueValue(ownerReadableStream));
762 }
763
764 if (stream[readableStreamCloseRequested] === true) {
765 FinishClosingReadableStream(stream);
766 } else {
767 ReleaseReadableStreamReader(reader);
768 }
769
770 return result;
771 };
772
773 exports.$stateInternal = function(stream) {
774 return stream[readableStreamState];
775 };
776
777 exports.$storedErrorInternal = function(stream) {
778 return stream[readableStreamStoredError];
779 };
780
781 exports.$lockForeverInternal = function(stream) {
782 AcquireReadableStreamReader(stream);
783 };
784 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698