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

Side by Side Diff: third_party/WebKit/Source/core/streams/WritableStream.js

Issue 2498983002: ReadableStream and WritableStream share strings (Closed)
Patch Set: Rebase to fix patch errors and fix typo Created 4 years 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
« no previous file with comments | « third_party/WebKit/Source/core/streams/ReadableStream.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Implementation of WritableStream for Blink. See 5 // Implementation of WritableStream for Blink. See
6 // https://streams.spec.whatwg.org/#ws. The implementation closely follows the 6 // https://streams.spec.whatwg.org/#ws. The implementation closely follows the
7 // standard, except where required for performance or integration with Blink. In 7 // standard, except where required for performance or integration with Blink. In
8 // particular, classes, methods and abstract operations are implemented in the 8 // particular, classes, methods and abstract operations are implemented in the
9 // same order as in the standard, to simplify side-by-side reading. 9 // same order as in the standard, to simplify side-by-side reading.
10 10
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 const Number = global.Number; 63 const Number = global.Number;
64 const Number_isNaN = Number.isNaN; 64 const Number_isNaN = Number.isNaN;
65 const Number_isFinite = Number.isFinite; 65 const Number_isFinite = Number.isFinite;
66 66
67 const Promise = global.Promise; 67 const Promise = global.Promise;
68 const thenPromise = v8.uncurryThis(Promise.prototype.then); 68 const thenPromise = v8.uncurryThis(Promise.prototype.then);
69 const Promise_resolve = v8.simpleBind(Promise.resolve, Promise); 69 const Promise_resolve = v8.simpleBind(Promise.resolve, Promise);
70 const Promise_reject = v8.simpleBind(Promise.reject, Promise); 70 const Promise_reject = v8.simpleBind(Promise.reject, Promise);
71 71
72 // User-visible strings. 72 // User-visible strings.
73 // TODO(ricea): Share strings with ReadableStream that are identical in both. 73 const streamErrors = binding.streamErrors;
74 const errIllegalInvocation = 'Illegal invocation'; 74 const errAbortLockedStream = 'Cannot abort a writable stream that is locked to a writer';
75 const errIllegalConstructor = 'Illegal constructor';
76 const errInvalidType = 'Invalid type is specified';
77 const errAbortLockedStream = 'Cannot abort a writable stream that is locked t o a writer';
78 const errStreamAborted = 'The stream has been aborted'; 75 const errStreamAborted = 'The stream has been aborted';
79 const errWriterLockReleasedPrefix = 'This writable stream writer has been rele ased and cannot be '; 76 const errWriterLockReleasedPrefix = 'This writable stream writer has been rele ased and cannot be ';
80 const errCloseCloseRequestedStream = 77 const errCloseCloseRequestedStream =
81 'Cannot close a writable stream that has already been requested to be clos ed'; 78 'Cannot close a writable stream that has already been requested to be clos ed';
82 const errWriteCloseRequestedStream = 79 const errWriteCloseRequestedStream =
83 'Cannot write to a writable stream that is due to be closed'; 80 'Cannot write to a writable stream that is due to be closed';
84 const templateErrorCannotActionOnStateStream = 81 const templateErrorCannotActionOnStateStream =
85 (action, state) => `Cannot ${action} a ${state} writable stream`; 82 (action, state) => `Cannot ${action} a ${state} writable stream`;
86 const errReleasedWriterClosedPromise = 83 const errReleasedWriterClosedPromise =
87 'This writable stream writer has been released and cannot be used to monit or the stream\'s state'; 84 'This writable stream writer has been released and cannot be used to monit or the stream\'s state';
88 const templateErrorIsNotAFunction = f => `${f} is not a function`; 85 const templateErrorIsNotAFunction = f => `${f} is not a function`;
89 const errSizeNotAFunction =
90 'A queuing strategy\'s size property must be a function';
91 const errInvalidHWM =
92 'A queuing strategy\'s highWaterMark property must be a non-negative, non- NaN number';
93 const errInvalidSize =
94 'The return value of a queuing strategy\'s size function must be a finite, non-NaN, non-negative number';
95 86
96 // These verbs are used after errWriterLockReleasedPrefix 87 // These verbs are used after errWriterLockReleasedPrefix
97 const verbUsedToGetTheDesiredSize = 'used to get the desiredSize'; 88 const verbUsedToGetTheDesiredSize = 'used to get the desiredSize';
98 const verbAborted = 'aborted'; 89 const verbAborted = 'aborted';
99 const verbClosed = 'closed'; 90 const verbClosed = 'closed';
100 const verbWrittenTo = 'written to'; 91 const verbWrittenTo = 'written to';
101 92
102 // Utility functions (not from the standard). 93 // Utility functions (not from the standard).
103 function createWriterLockReleasedError(verb) { 94 function createWriterLockReleasedError(verb) {
104 return new TypeError(errWriterLockReleasedPrefix + verb); 95 return new TypeError(errWriterLockReleasedPrefix + verb);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 156
166 class WritableStream { 157 class WritableStream {
167 constructor(underlyingSink = {}, { size, highWaterMark = 1 } = {}) { 158 constructor(underlyingSink = {}, { size, highWaterMark = 1 } = {}) {
168 this[_state] = WRITABLE; 159 this[_state] = WRITABLE;
169 this[_storedError] = undefined; 160 this[_storedError] = undefined;
170 this[_writer] = undefined; 161 this[_writer] = undefined;
171 this[_writableStreamController] = undefined; 162 this[_writableStreamController] = undefined;
172 this[_writeRequests] = new v8.InternalPackedArray(); 163 this[_writeRequests] = new v8.InternalPackedArray();
173 const type = underlyingSink.type; 164 const type = underlyingSink.type;
174 if (type !== undefined) { 165 if (type !== undefined) {
175 throw new RangeError(errInvalidType); 166 throw new RangeError(streamErrors.invalidType);
176 } 167 }
177 this[_writableStreamController] = 168 this[_writableStreamController] =
178 new WritableStreamDefaultController(this, underlyingSink, size, 169 new WritableStreamDefaultController(this, underlyingSink, size,
179 highWaterMark); 170 highWaterMark);
180 } 171 }
181 172
182 get locked() { 173 get locked() {
183 if (!IsWritableStream(this)) { 174 if (!IsWritableStream(this)) {
184 throw new TypeError(errIllegalInvocation); 175 throw new TypeError(streamErrors.illegalInvocation);
185 } 176 }
186 return IsWritableStreamLocked(this); 177 return IsWritableStreamLocked(this);
187 } 178 }
188 179
189 abort(reason) { 180 abort(reason) {
190 if (!IsWritableStream(this)) { 181 if (!IsWritableStream(this)) {
191 return Promise_reject(new TypeError(errIllegalInvocation)); 182 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
192 } 183 }
193 if (IsWritableStreamLocked(this)) { 184 if (IsWritableStreamLocked(this)) {
194 return Promise_reject(new TypeError(errAbortLockedStream)); 185 return Promise_reject(new TypeError(errAbortLockedStream));
195 } 186 }
196 return WritableStreamAbort(this, reason); 187 return WritableStreamAbort(this, reason);
197 } 188 }
198 189
199 getWriter() { 190 getWriter() {
200 if (!IsWritableStream(this)) { 191 if (!IsWritableStream(this)) {
201 throw new TypeError(errIllegalInvocation); 192 throw new TypeError(streamErrors.illegalInvocation);
202 } 193 }
203 return AcquireWritableStreamDefaultWriter(this); 194 return AcquireWritableStreamDefaultWriter(this);
204 } 195 }
205 } 196 }
206 197
207 // General Writable Stream Abstract Operations 198 // General Writable Stream Abstract Operations
208 199
209 function AcquireWritableStreamDefaultWriter(stream) { 200 function AcquireWritableStreamDefaultWriter(stream) {
210 return new WritableStreamDefaultWriter(stream); 201 return new WritableStreamDefaultWriter(stream);
211 } 202 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } else { 288 } else {
298 TEMP_ASSERT(backpressure === false, 289 TEMP_ASSERT(backpressure === false,
299 'backpressure is false.'); 290 'backpressure is false.');
300 v8.resolvePromise(writer[_readyPromise], undefined); 291 v8.resolvePromise(writer[_readyPromise], undefined);
301 } 292 }
302 } 293 }
303 294
304 class WritableStreamDefaultWriter { 295 class WritableStreamDefaultWriter {
305 constructor(stream) { 296 constructor(stream) {
306 if (!IsWritableStream(stream)) { 297 if (!IsWritableStream(stream)) {
307 throw new TypeError(errIllegalConstructor); 298 throw new TypeError(streamErrors.illegalConstructor);
308 } 299 }
309 if (IsWritableStreamLocked(stream)) { 300 if (IsWritableStreamLocked(stream)) {
310 throw new TypeError(errIllegalConstructor); 301 throw new TypeError(streamErrors.illegalConstructor);
311 } 302 }
312 this[_ownerWritableStream] = stream; 303 this[_ownerWritableStream] = stream;
313 stream[_writer] = this; 304 stream[_writer] = this;
314 const state = stream[_state]; 305 const state = stream[_state];
315 if (state === WRITABLE || state === CLOSING) { 306 if (state === WRITABLE || state === CLOSING) {
316 this[_closedPromise] = v8.createPromise(); 307 this[_closedPromise] = v8.createPromise();
317 } else if (state === CLOSED) { 308 } else if (state === CLOSED) {
318 this[_closedPromise] = Promise_resolve(undefined); 309 this[_closedPromise] = Promise_resolve(undefined);
319 } else { 310 } else {
320 TEMP_ASSERT(state === ERRORED, 311 TEMP_ASSERT(state === ERRORED,
321 'state is "errored".'); 312 'state is "errored".');
322 this[_closedPromise] = Promise_reject(stream[_storedError]); 313 this[_closedPromise] = Promise_reject(stream[_storedError]);
323 } 314 }
324 if (state === WRITABLE && 315 if (state === WRITABLE &&
325 WritableStreamDefaultControllerGetBackpressure( 316 WritableStreamDefaultControllerGetBackpressure(
326 stream[_writableStreamController])) { 317 stream[_writableStreamController])) {
327 this[_readyPromise] = v8.createPromise(); 318 this[_readyPromise] = v8.createPromise();
328 } else { 319 } else {
329 this[_readyPromise] = Promise_resolve(undefined); 320 this[_readyPromise] = Promise_resolve(undefined);
330 } 321 }
331 } 322 }
332 323
333 get closed() { 324 get closed() {
334 if (!IsWritableStreamDefaultWriter(this)) { 325 if (!IsWritableStreamDefaultWriter(this)) {
335 return Promise_reject(new TypeError(errIllegalInvocation)); 326 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
336 } 327 }
337 return this[_closedPromise]; 328 return this[_closedPromise];
338 } 329 }
339 330
340 get desiredSize() { 331 get desiredSize() {
341 if (!IsWritableStreamDefaultWriter(this)) { 332 if (!IsWritableStreamDefaultWriter(this)) {
342 throw new TypeError(errIllegalInvocation); 333 throw new TypeError(streamErrors.illegalInvocation);
343 } 334 }
344 if (this[_ownerWritableStream] === undefined) { 335 if (this[_ownerWritableStream] === undefined) {
345 throw createWriterLockReleasedError(verbUsedToGetTheDesiredSize); 336 throw createWriterLockReleasedError(verbUsedToGetTheDesiredSize);
346 } 337 }
347 return WritableStreamDefaultWriterGetDesiredSize(this); 338 return WritableStreamDefaultWriterGetDesiredSize(this);
348 } 339 }
349 340
350 get ready() { 341 get ready() {
351 if (!IsWritableStreamDefaultWriter(this)) { 342 if (!IsWritableStreamDefaultWriter(this)) {
352 return Promise_reject(new TypeError(errIllegalInvocation)); 343 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
353 } 344 }
354 return this[_readyPromise]; 345 return this[_readyPromise];
355 } 346 }
356 347
357 abort(reason) { 348 abort(reason) {
358 if (!IsWritableStreamDefaultWriter(this)) { 349 if (!IsWritableStreamDefaultWriter(this)) {
359 return Promise_reject(new TypeError(errIllegalInvocation)); 350 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
360 } 351 }
361 if (this[_ownerWritableStream] === undefined) { 352 if (this[_ownerWritableStream] === undefined) {
362 return Promise_reject(createWriterLockReleasedError(verbAborted)); 353 return Promise_reject(createWriterLockReleasedError(verbAborted));
363 } 354 }
364 return WritableStreamDefaultWriterAbort(this, reason); 355 return WritableStreamDefaultWriterAbort(this, reason);
365 } 356 }
366 357
367 close() { 358 close() {
368 if (!IsWritableStreamDefaultWriter(this)) { 359 if (!IsWritableStreamDefaultWriter(this)) {
369 return Promise_reject(new TypeError(errIllegalInvocation)); 360 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
370 } 361 }
371 const stream = this[_ownerWritableStream]; 362 const stream = this[_ownerWritableStream];
372 if (stream === undefined) { 363 if (stream === undefined) {
373 return Promise_reject(createWriterLockReleasedError(verbClosed)); 364 return Promise_reject(createWriterLockReleasedError(verbClosed));
374 } 365 }
375 if (stream[_state] === CLOSING) { 366 if (stream[_state] === CLOSING) {
376 return Promise_reject(new TypeError(errCloseCloseRequestedStream)); 367 return Promise_reject(new TypeError(errCloseCloseRequestedStream));
377 } 368 }
378 return WritableStreamDefaultWriterClose(this); 369 return WritableStreamDefaultWriterClose(this);
379 } 370 }
380 371
381 releaseLock() { 372 releaseLock() {
382 if (!IsWritableStreamDefaultWriter(this)) { 373 if (!IsWritableStreamDefaultWriter(this)) {
383 throw new TypeError(errIllegalInvocation); 374 throw new TypeError(streamErrors.illegalInvocation);
384 } 375 }
385 const stream = this[_ownerWritableStream]; 376 const stream = this[_ownerWritableStream];
386 if (stream === undefined) { 377 if (stream === undefined) {
387 return; 378 return;
388 } 379 }
389 TEMP_ASSERT(stream[_writer] !== undefined, 380 TEMP_ASSERT(stream[_writer] !== undefined,
390 'stream.[[writer]] is not undefined.'); 381 'stream.[[writer]] is not undefined.');
391 WritableStreamDefaultWriterRelease(this); 382 WritableStreamDefaultWriterRelease(this);
392 } 383 }
393 384
394 write(chunk) { 385 write(chunk) {
395 if (!IsWritableStreamDefaultWriter(this)) { 386 if (!IsWritableStreamDefaultWriter(this)) {
396 return Promise_reject(new TypeError(errIllegalInvocation)); 387 return Promise_reject(new TypeError(streamErrors.illegalInvocation));
397 } 388 }
398 const stream = this[_ownerWritableStream]; 389 const stream = this[_ownerWritableStream];
399 if (stream === undefined) { 390 if (stream === undefined) {
400 return Promise_reject(createWriterLockReleasedError(verbWrittenTo)); 391 return Promise_reject(createWriterLockReleasedError(verbWrittenTo));
401 } 392 }
402 if (stream[_state] === CLOSING) { 393 if (stream[_state] === CLOSING) {
403 return Promise_reject(new TypeError(errWriteCloseRequestedStream)); 394 return Promise_reject(new TypeError(errWriteCloseRequestedStream));
404 } 395 }
405 return WritableStreamDefaultWriterWrite(this, chunk); 396 return WritableStreamDefaultWriterWrite(this, chunk);
406 } 397 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 'state is "writable".'); 481 'state is "writable".');
491 const promise = WritableStreamAddWriteRequest(stream); 482 const promise = WritableStreamAddWriteRequest(stream);
492 WritableStreamDefaultControllerWrite(stream[_writableStreamController], 483 WritableStreamDefaultControllerWrite(stream[_writableStreamController],
493 chunk); 484 chunk);
494 return promise; 485 return promise;
495 } 486 }
496 487
497 class WritableStreamDefaultController { 488 class WritableStreamDefaultController {
498 constructor(stream, underlyingSink, size, highWaterMark) { 489 constructor(stream, underlyingSink, size, highWaterMark) {
499 if (!IsWritableStream(stream)) { 490 if (!IsWritableStream(stream)) {
500 throw new TypeError(errIllegalConstructor); 491 throw new TypeError(streamErrors.illegalConstructor);
501 } 492 }
502 if (stream[_writableStreamController] !== undefined) { 493 if (stream[_writableStreamController] !== undefined) {
503 throw new TypeError(errIllegalConstructor); 494 throw new TypeError(streamErrors.illegalConstructor);
504 } 495 }
505 this[_controlledWritableStream] = stream; 496 this[_controlledWritableStream] = stream;
506 this[_underlyingSink] = underlyingSink; 497 this[_underlyingSink] = underlyingSink;
507 this[_queue] = new v8.InternalPackedArray(); 498 this[_queue] = new v8.InternalPackedArray();
508 this[_queueSize] = 0; 499 this[_queueSize] = 0;
509 this[_defaultControllerFlags] = 0; 500 this[_defaultControllerFlags] = 0;
510 const normalizedStrategy = 501 const normalizedStrategy =
511 ValidateAndNormalizeQueuingStrategy(size, highWaterMark); 502 ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
512 this[_strategySize] = normalizedStrategy.size; 503 this[_strategySize] = normalizedStrategy.size;
513 this[_strategyHWM] = normalizedStrategy.highWaterMark; 504 this[_strategyHWM] = normalizedStrategy.highWaterMark;
514 const backpressure = WritableStreamDefaultControllerGetBackpressure(this); 505 const backpressure = WritableStreamDefaultControllerGetBackpressure(this);
515 if (backpressure) { 506 if (backpressure) {
516 WritableStreamUpdateBackpressure(stream, backpressure); 507 WritableStreamUpdateBackpressure(stream, backpressure);
517 } 508 }
518 const controller = this; 509 const controller = this;
519 const startResult = InvokeOrNoop(underlyingSink, 'start', [this]); 510 const startResult = InvokeOrNoop(underlyingSink, 'start', [this]);
520 const onFulfilled = () => { 511 const onFulfilled = () => {
521 setDefaultControllerStartedFlag(controller, true); 512 setDefaultControllerStartedFlag(controller, true);
522 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); 513 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
523 }; 514 };
524 const onRejected = r => { 515 const onRejected = r => {
525 WritableStreamDefaultControllerErrorIfNeeded(controller, r); 516 WritableStreamDefaultControllerErrorIfNeeded(controller, r);
526 }; 517 };
527 thenPromise(Promise_resolve(startResult), onFulfilled, onRejected); 518 thenPromise(Promise_resolve(startResult), onFulfilled, onRejected);
528 } 519 }
529 520
530 error(e) { 521 error(e) {
531 if (!IsWritableStreamDefaultController(this)) { 522 if (!IsWritableStreamDefaultController(this)) {
532 throw new TypeError(errIllegalInvocation); 523 throw new TypeError(streamErrors.illegalInvocation);
533 } 524 }
534 const state = this[_controlledWritableStream][_state]; 525 const state = this[_controlledWritableStream][_state];
535 if (state === CLOSED || state === ERRORED) { 526 if (state === CLOSED || state === ERRORED) {
536 throw createCannotActionOnStateStreamError('error', state); 527 throw createCannotActionOnStateStreamError('error', state);
537 } 528 }
538 WritableStreamDefaultControllerError(this, e); 529 WritableStreamDefaultControllerError(this, e);
539 } 530 }
540 } 531 }
541 532
542 // Writable Stream Default Controller Abstract Operations 533 // Writable Stream Default Controller Abstract Operations
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 TEMP_ASSERT(controller[_queue].length !== 0, 697 TEMP_ASSERT(controller[_queue].length !== 0,
707 'queue is not empty.'); 698 'queue is not empty.');
708 const result = controller[_queue].shift(); 699 const result = controller[_queue].shift();
709 controller[_queueSize] -= result.size; 700 controller[_queueSize] -= result.size;
710 return result.value; 701 return result.value;
711 } 702 }
712 703
713 function EnqueueValueWithSizeForController(controller, value, size) { 704 function EnqueueValueWithSizeForController(controller, value, size) {
714 size = Number(size); 705 size = Number(size);
715 if (!IsFiniteNonNegativeNumber(size)) { 706 if (!IsFiniteNonNegativeNumber(size)) {
716 throw new RangeError(errInvalidSize); 707 throw new RangeError(streamErrors.invalidSize);
717 } 708 }
718 709
719 controller[_queueSize] += size; 710 controller[_queueSize] += size;
720 controller[_queue].push({value, size}); 711 controller[_queue].push({value, size});
721 } 712 }
722 713
723 function GetTotalQueueSizeForController(controller) { 714 function GetTotalQueueSizeForController(controller) {
724 return controller[_queueSize]; 715 return controller[_queueSize];
725 } 716 }
726 717
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 try { 771 try {
781 return Promise_resolve(InvokeOrNoop(O, P, args)); 772 return Promise_resolve(InvokeOrNoop(O, P, args));
782 } catch (e) { 773 } catch (e) {
783 return Promise_reject(e); 774 return Promise_reject(e);
784 } 775 }
785 } 776 }
786 777
787 // TODO(ricea): Share this operation with ReadableStream.js. 778 // TODO(ricea): Share this operation with ReadableStream.js.
788 function ValidateAndNormalizeQueuingStrategy(size, highWaterMark) { 779 function ValidateAndNormalizeQueuingStrategy(size, highWaterMark) {
789 if (size !== undefined && typeof size !== 'function') { 780 if (size !== undefined && typeof size !== 'function') {
790 throw new TypeError(errSizeNotAFunction); 781 throw new TypeError(streamErrors.sizeNotAFunction);
791 } 782 }
792 783
793 highWaterMark = Number(highWaterMark); 784 highWaterMark = Number(highWaterMark);
794 if (Number_isNaN(highWaterMark) || highWaterMark < 0) { 785 if (Number_isNaN(highWaterMark)) {
795 throw new RangeError(errInvalidHWM); 786 throw new RangeError(streamErrors.errInvalidHWM);
787 }
788 if (highWaterMark < 0) {
789 throw new RangeError(streamErrors.invalidHWM);
796 } 790 }
797 791
798 return {size, highWaterMark}; 792 return {size, highWaterMark};
799 } 793 }
800 794
801 // 795 //
802 // Additions to the global object 796 // Additions to the global object
803 // 797 //
804 798
805 defineProperty(global, 'WritableStream', { 799 defineProperty(global, 'WritableStream', {
806 value: WritableStream, 800 value: WritableStream,
807 enumerable: false, 801 enumerable: false,
808 configurable: true, 802 configurable: true,
809 writable: true 803 writable: true
810 }); 804 });
811 805
812 // TODO(ricea): Exports to Blink 806 // TODO(ricea): Exports to Blink
813 }); 807 });
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/streams/ReadableStream.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698