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

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

Issue 2596883002: Update writable streams for the latest spec changes (Closed)
Patch Set: Adjust indents Created 3 years, 11 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
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/general.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
11 (function(global, binding, v8) { 11 (function(global, binding, v8) {
12 'use strict'; 12 'use strict';
13 13
14 // Private symbols. These correspond to the internal slots in the standard. 14 // Private symbols. These correspond to the internal slots in the standard.
15 // "[[X]]" in the standard is spelt _X in this implementation. 15 // "[[X]]" in the standard is spelt _X in this implementation.
16 const _pendingWriteRequest = v8.createPrivateSymbol('[[pendingWriteRequest]]') ;
17 const _pendingCloseRequest = v8.createPrivateSymbol('[[pendingCloseRequest]]') ;
18 const _pendingAbortRequest = v8.createPrivateSymbol('[[pendingAbortRequest]]') ;
16 const _state = v8.createPrivateSymbol('[[state]]'); 19 const _state = v8.createPrivateSymbol('[[state]]');
17 const _storedError = v8.createPrivateSymbol('[[storedError]]'); 20 const _storedError = v8.createPrivateSymbol('[[storedError]]');
18 const _writer = v8.createPrivateSymbol('[[writer]]'); 21 const _writer = v8.createPrivateSymbol('[[writer]]');
19 const _writableStreamController = 22 const _writableStreamController =
20 v8.createPrivateSymbol('[[writableStreamController]]'); 23 v8.createPrivateSymbol('[[writableStreamController]]');
21 const _writeRequests = v8.createPrivateSymbol('[[writeRequests]]'); 24 const _writeRequests = v8.createPrivateSymbol('[[writeRequests]]');
22 const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]'); 25 const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]');
23 const _ownerWritableStream = 26 const _ownerWritableStream =
24 v8.createPrivateSymbol('[[ownerWritableStream]]'); 27 v8.createPrivateSymbol('[[ownerWritableStream]]');
25 const _readyPromise = v8.createPrivateSymbol('[[readyPromise]]'); 28 const _readyPromise = v8.createPrivateSymbol('[[readyPromise]]');
26 const _controlledWritableStream = 29 const _controlledWritableStream =
27 v8.createPrivateSymbol('[[controlledWritableStream]]'); 30 v8.createPrivateSymbol('[[controlledWritableStream]]');
28 const _queue = v8.createPrivateSymbol('[[queue]]'); 31 const _queue = v8.createPrivateSymbol('[[queue]]');
29 const _queueSize = v8.createPrivateSymbol('[[queueSize]]'); 32 const _queueSize = v8.createPrivateSymbol('[[queueSize]]');
30 const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]'); 33 const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]');
31 const _strategySize = v8.createPrivateSymbol('[[strategySize]]'); 34 const _strategySize = v8.createPrivateSymbol('[[strategySize]]');
32 const _underlyingSink = v8.createPrivateSymbol('[[underlyingSink]]'); 35 const _underlyingSink = v8.createPrivateSymbol('[[underlyingSink]]');
33 36
34 // _defaultControllerFlags combines WritableStreamDefaultController's internal 37 // _defaultControllerFlags combines WritableStreamDefaultController's internal
35 // slots [[started]] and [[writing]] into a single bitmask for efficiency. 38 // slots [[started]], [[writing]], and [[inClose]] into a single bitmask for
39 // efficiency.
36 const _defaultControllerFlags = 40 const _defaultControllerFlags =
37 v8.createPrivateSymbol('[[defaultControllerFlags]]'); 41 v8.createPrivateSymbol('[[defaultControllerFlags]]');
38 const FLAG_STARTED = 0b1; 42 const FLAG_STARTED = 0b1;
39 const FLAG_WRITING = 0b10; 43 const FLAG_WRITING = 0b10;
44 const FLAG_INCLOSE = 0b100;
40 45
41 // For efficiency, WritableStream [[state]] contains numeric values. 46 // For efficiency, WritableStream [[state]] contains numeric values.
42 const WRITABLE = 0; 47 const WRITABLE = 0;
43 const CLOSING = 1; 48 const CLOSING = 1;
44 const CLOSED = 2; 49 const CLOSED = 2;
45 const ERRORED = 3; 50 const ERRORED = 3;
46 51
47 // Javascript functions. It is important to use these copies, as the ones on 52 // Javascript functions. It is important to use these copies, as the ones on
48 // the global object may have been overwritten. See "V8 Extras Design Doc", 53 // the global object may have been overwritten. See "V8 Extras Design Doc",
49 // section "Security Considerations". 54 // section "Security Considerations".
50 // https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA 8Ec0/edit#heading=h.9yixony1a18r 55 // https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA 8Ec0/edit#heading=h.9yixony1a18r
51 const undefined = global.undefined; 56 const undefined = global.undefined;
52 57
53 const defineProperty = global.Object.defineProperty; 58 const defineProperty = global.Object.defineProperty;
54 const hasOwnProperty = v8.uncurryThis(global.Object.hasOwnProperty); 59 const hasOwnProperty = v8.uncurryThis(global.Object.hasOwnProperty);
55 60
56 const Function_call = v8.uncurryThis(global.Function.prototype.call);
57 const Function_apply = v8.uncurryThis(global.Function.prototype.apply); 61 const Function_apply = v8.uncurryThis(global.Function.prototype.apply);
58 62
59 const TypeError = global.TypeError; 63 const TypeError = global.TypeError;
60 const RangeError = global.RangeError; 64 const RangeError = global.RangeError;
61 65
62 const Boolean = global.Boolean; 66 const Boolean = global.Boolean;
63 const Number = global.Number; 67 const Number = global.Number;
64 const Number_isNaN = Number.isNaN; 68 const Number_isNaN = Number.isNaN;
65 const Number_isFinite = Number.isFinite; 69 const Number_isFinite = Number.isFinite;
66 70
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 } 126 }
123 127
124 function getDefaultControllerWritingFlag(controller) { 128 function getDefaultControllerWritingFlag(controller) {
125 return Boolean(controller[_defaultControllerFlags] & FLAG_WRITING); 129 return Boolean(controller[_defaultControllerFlags] & FLAG_WRITING);
126 } 130 }
127 131
128 function setDefaultControllerWritingFlag(controller, value) { 132 function setDefaultControllerWritingFlag(controller, value) {
129 setDefaultControllerFlag(controller, FLAG_WRITING, value); 133 setDefaultControllerFlag(controller, FLAG_WRITING, value);
130 } 134 }
131 135
136 function getDefaultControllerInCloseFlag(controller) {
137 return Boolean(controller[_defaultControllerFlags] & FLAG_INCLOSE);
138 }
139
140 function setDefaultControllerInCloseFlag(controller, value) {
141 setDefaultControllerFlag(controller, FLAG_INCLOSE, value);
142 }
143
132 function rejectPromises(array, e) { 144 function rejectPromises(array, e) {
133 // array is an InternalPackedArray so forEach won't work. 145 // array is an InternalPackedArray so forEach won't work.
134 for (let i = 0; i < array.length; ++i) { 146 for (let i = 0; i < array.length; ++i) {
135 v8.rejectPromise(array[i], e); 147 v8.rejectPromise(array[i], e);
136 } 148 }
137 } 149 }
138 150
139 // https://tc39.github.io/ecma262/#sec-ispropertykey 151 // https://tc39.github.io/ecma262/#sec-ispropertykey
140 // TODO(ricea): Remove this when the asserts using it are removed. 152 // TODO(ricea): Remove this when the asserts using it are removed.
141 function IsPropertyKey(argument) { 153 function IsPropertyKey(argument) {
142 return typeof argument === 'string' || typeof argument === 'symbol'; 154 return typeof argument === 'string' || typeof argument === 'symbol';
143 } 155 }
144 156
145 // TODO(ricea): Remove all asserts once the implementation has stabilised. 157 // TODO(ricea): Remove all asserts once the implementation has stabilised.
146 function TEMP_ASSERT(predicate, message) { 158 function TEMP_ASSERT(predicate, message) {
147 if (predicate) { 159 if (predicate) {
148 return; 160 return;
149 } 161 }
150 v8.log(`Assertion failed: ${message}\n`); 162 v8.log(`Assertion failed: ${message}\n`);
151 v8.logStackTrace(); 163 v8.logStackTrace();
152 class WritableStreamInternalError { 164 class WritableStreamInternalError extends Error {
165 constructor(message) {
166 super(message);
167 }
153 } 168 }
154 throw new WritableStreamInternalError(); 169 throw new WritableStreamInternalError(message);
155 } 170 }
156 171
157 class WritableStream { 172 class WritableStream {
158 constructor(underlyingSink = {}, { size, highWaterMark = 1 } = {}) { 173 constructor(underlyingSink = {}, { size, highWaterMark = 1 } = {}) {
159 this[_state] = WRITABLE; 174 this[_state] = WRITABLE;
160 this[_storedError] = undefined; 175 this[_storedError] = undefined;
161 this[_writer] = undefined; 176 this[_writer] = undefined;
162 this[_writableStreamController] = undefined; 177 this[_writableStreamController] = undefined;
178 this[_pendingWriteRequest] = undefined;
179 this[_pendingCloseRequest] = undefined;
180 this[_pendingAbortRequest] = undefined;
163 this[_writeRequests] = new v8.InternalPackedArray(); 181 this[_writeRequests] = new v8.InternalPackedArray();
164 const type = underlyingSink.type; 182 const type = underlyingSink.type;
165 if (type !== undefined) { 183 if (type !== undefined) {
166 throw new RangeError(streamErrors.invalidType); 184 throw new RangeError(streamErrors.invalidType);
167 } 185 }
168 this[_writableStreamController] = 186 this[_writableStreamController] =
169 new WritableStreamDefaultController(this, underlyingSink, size, 187 new WritableStreamDefaultController(this, underlyingSink, size,
170 highWaterMark); 188 highWaterMark);
171 } 189 }
172 190
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 if (state === CLOSED) { 234 if (state === CLOSED) {
217 return Promise_resolve(undefined); 235 return Promise_resolve(undefined);
218 } 236 }
219 if (state === ERRORED) { 237 if (state === ERRORED) {
220 return Promise_reject(stream[_storedError]); 238 return Promise_reject(stream[_storedError]);
221 } 239 }
222 TEMP_ASSERT(state === WRITABLE || state === CLOSING, 240 TEMP_ASSERT(state === WRITABLE || state === CLOSING,
223 'state is "writable" or "closing".'); 241 'state is "writable" or "closing".');
224 const error = new TypeError(errStreamAborted); 242 const error = new TypeError(errStreamAborted);
225 WritableStreamError(stream, error); 243 WritableStreamError(stream, error);
226 return WritableStreamDefaultControllerAbort( 244
227 stream[_writableStreamController], reason); 245 const controller = stream[_writableStreamController];
246 TEMP_ASSERT(controller !== undefined,
247 'controller is not undefined');
248
249 const isWriting = getDefaultControllerWritingFlag(controller);
250 if (isWriting || getDefaultControllerInCloseFlag(controller)) {
251 const promise = v8.createPromise();
252 stream[_pendingAbortRequest] = promise;
253
254 if (isWriting) {
255 return thenPromise(promise, () => {
256 return WritableStreamDefaultControllerAbort(controller, reason);
257 });
258 }
259 return promise;
260 }
261
262 return WritableStreamDefaultControllerAbort(controller, reason);
228 } 263 }
229 264
230 // Writable Stream Abstract Operations Used by Controllers 265 // Writable Stream Abstract Operations Used by Controllers
231 266
232 function WritableStreamAddWriteRequest(stream) { 267 function WritableStreamAddWriteRequest(stream) {
233 TEMP_ASSERT(IsWritableStreamLocked(stream), 268 TEMP_ASSERT(IsWritableStreamLocked(stream),
234 '! IsWritableStreamLocked(writer) is true.'); 269 '! IsWritableStreamLocked(writer) is true.');
235 TEMP_ASSERT(stream[_state] === WRITABLE, 270 TEMP_ASSERT(stream[_state] === WRITABLE,
236 'stream.[[state]] is "writable".'); 271 'stream.[[state]] is "writable".');
237 const promise = v8.createPromise(); 272 const promise = v8.createPromise();
238 stream[_writeRequests].push(promise); 273 stream[_writeRequests].push(promise);
239 return promise; 274 return promise;
240 } 275 }
241 276
242 function WritableStreamError(stream, e) { 277 function WritableStreamError(stream, e) {
243 const state = stream[_state]; 278 const oldState = stream[_state];
244 TEMP_ASSERT(state === WRITABLE || state === CLOSING, 279 TEMP_ASSERT(oldState === WRITABLE || oldState === CLOSING,
245 'state is "writable" or "closing".'); 280 'oldState is "writable" or "closing".');
246 rejectPromises(stream[_writeRequests], e); 281
247 stream[_writeRequests] = new v8.InternalPackedArray(); 282 stream[_state] = ERRORED;
283 stream[_storedError] = e;
284
285 const controller = stream[_writableStreamController];
286 if (controller === undefined ||
287 (!getDefaultControllerWritingFlag(controller) &&
288 !getDefaultControllerInCloseFlag(controller))) {
289 WritableStreamRejectPromisesInReactionToError(stream);
290 }
291
248 const writer = stream[_writer]; 292 const writer = stream[_writer];
249 if (writer !== undefined) { 293 if (writer !== undefined) {
250 v8.rejectPromise(writer[_closedPromise], e); 294 if (oldState === WRITABLE &&
251 if (state === WRITABLE && 295 WritableStreamDefaultControllerGetBackpressure(controller) === true) {
252 WritableStreamDefaultControllerGetBackpressure(
253 stream[_writableStreamController])) {
254 v8.rejectPromise(writer[_readyPromise], e); 296 v8.rejectPromise(writer[_readyPromise], e);
255 } else { 297 } else {
256 writer[_readyPromise] = Promise_reject(e); 298 writer[_readyPromise] = Promise_reject(e);
257 } 299 }
300 v8.markPromiseAsHandled(writer[_readyPromise]);
258 } 301 }
259 stream[_state] = ERRORED;
260 stream[_storedError] = e;
261 } 302 }
262 303
263 function WritableStreamFinishClose(stream) { 304 function WritableStreamFinishClose(stream) {
264 TEMP_ASSERT(stream[_state] === CLOSING, 305 const state = stream[_state];
265 'stream.[[state]] is "closing".'); 306 TEMP_ASSERT(state === CLOSING || state === ERRORED,
266 TEMP_ASSERT(stream[_writer] !== undefined, 307 'state is "closing" or "errored"');
267 'stream.[[writer]] is not undefined.'); 308
268 stream[_state] = CLOSED; 309 if (state === CLOSING) {
269 v8.resolvePromise(stream[_writer][_closedPromise], undefined); 310 v8.resolvePromise(stream[_writer][_closedPromise], undefined);
311 stream[_state] = CLOSED;
312 } else {
313 TEMP_ASSERT(state === ERRORED, 'state is "errored"');
314 v8.rejectPromise(stream[_writer][_closedPromise], stream[_storedError]);
315 v8.markPromiseAsHandled(stream[_writer][_closedPromise]);
316 }
317
318 if (stream[_pendingAbortRequest] !== undefined) {
319 v8.resolvePromise(stream[_pendingAbortRequest], undefined);
320 stream[_pendingAbortRequest] = undefined;
321 }
270 } 322 }
271 323
272 function WritableStreamFulfillWriteRequest(stream) { 324 function WritableStreamRejectPromisesInReactionToError(stream) {
273 TEMP_ASSERT(stream[_writeRequests].length !== 0, 325 TEMP_ASSERT(stream[_state] === ERRORED, 'stream.[[state]] is "errored"');
274 'stream.[[writeRequests]] is not empty.'); 326 TEMP_ASSERT(stream[_pendingWriteRequest] === undefined,
275 const writeRequest = stream[_writeRequests].shift(); 327 'stream.[[pendingWriteRequest]] is undefined');
276 v8.resolvePromise(writeRequest, undefined); 328
329 const storedError = stream[_storedError];
330 rejectPromises(stream[_writeRequests], storedError);
331 stream[_writeRequests] = new v8.InternalPackedArray();
332
333 if (stream[_pendingCloseRequest] !== undefined) {
334 TEMP_ASSERT(
335 getDefaultControllerInCloseFlag(stream[_writableStreamController]) ===
336 false, 'stream.[[writableStreamController]].[[inClose]] === false');
337 v8.rejectPromise(stream[_pendingCloseRequest], storedError);
338 stream[_pendingCloseRequest] = undefined;
339 }
340
341 const writer = stream[_writer];
342 if (writer !== undefined) {
343 v8.rejectPromise(writer[_closedPromise], storedError);
344 v8.markPromiseAsHandled(writer[_closedPromise]);
345 }
277 } 346 }
278 347
279 function WritableStreamUpdateBackpressure(stream, backpressure) { 348 function WritableStreamUpdateBackpressure(stream, backpressure) {
280 TEMP_ASSERT(stream[_state] === WRITABLE, 349 TEMP_ASSERT(stream[_state] === WRITABLE,
281 'stream.[[state]] is "writable".'); 350 'stream.[[state]] is "writable".');
282 const writer = stream[_writer]; 351 const writer = stream[_writer];
283 if (writer === undefined) { 352 if (writer === undefined) {
284 return; 353 return;
285 } 354 }
286 if (backpressure) { 355 if (backpressure) {
(...skipping 17 matching lines...) Expand all
304 stream[_writer] = this; 373 stream[_writer] = this;
305 const state = stream[_state]; 374 const state = stream[_state];
306 if (state === WRITABLE || state === CLOSING) { 375 if (state === WRITABLE || state === CLOSING) {
307 this[_closedPromise] = v8.createPromise(); 376 this[_closedPromise] = v8.createPromise();
308 } else if (state === CLOSED) { 377 } else if (state === CLOSED) {
309 this[_closedPromise] = Promise_resolve(undefined); 378 this[_closedPromise] = Promise_resolve(undefined);
310 } else { 379 } else {
311 TEMP_ASSERT(state === ERRORED, 380 TEMP_ASSERT(state === ERRORED,
312 'state is "errored".'); 381 'state is "errored".');
313 this[_closedPromise] = Promise_reject(stream[_storedError]); 382 this[_closedPromise] = Promise_reject(stream[_storedError]);
383 v8.markPromiseAsHandled(this[_closedPromise]);
314 } 384 }
315 if (state === WRITABLE && 385 if (state === WRITABLE &&
316 WritableStreamDefaultControllerGetBackpressure( 386 WritableStreamDefaultControllerGetBackpressure(
317 stream[_writableStreamController])) { 387 stream[_writableStreamController])) {
318 this[_readyPromise] = v8.createPromise(); 388 this[_readyPromise] = v8.createPromise();
319 } else { 389 } else {
320 this[_readyPromise] = Promise_resolve(undefined); 390 this[_readyPromise] = Promise_resolve(undefined);
321 } 391 }
322 } 392 }
323 393
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 const stream = writer[_ownerWritableStream]; 484 const stream = writer[_ownerWritableStream];
415 TEMP_ASSERT(stream !== undefined, 485 TEMP_ASSERT(stream !== undefined,
416 'stream is not undefined.'); 486 'stream is not undefined.');
417 const state = stream[_state]; 487 const state = stream[_state];
418 if (state === CLOSED || state === ERRORED) { 488 if (state === CLOSED || state === ERRORED) {
419 return Promise_reject( 489 return Promise_reject(
420 createCannotActionOnStateStreamError('close', state)); 490 createCannotActionOnStateStreamError('close', state));
421 } 491 }
422 TEMP_ASSERT(state === WRITABLE, 492 TEMP_ASSERT(state === WRITABLE,
423 'state is "writable".'); 493 'state is "writable".');
424 const promise = WritableStreamAddWriteRequest(stream); 494 stream[_pendingCloseRequest] = v8.createPromise();
425 if (WritableStreamDefaultControllerGetBackpressure( 495 if (WritableStreamDefaultControllerGetBackpressure(
426 stream[_writableStreamController])) { 496 stream[_writableStreamController])) {
427 v8.resolvePromise(writer[_readyPromise], undefined); 497 v8.resolvePromise(writer[_readyPromise], undefined);
428 } 498 }
429 stream[_state] = CLOSING; 499 stream[_state] = CLOSING;
430 WritableStreamDefaultControllerClose(stream[_writableStreamController]); 500 WritableStreamDefaultControllerClose(stream[_writableStreamController]);
431 return promise; 501 return stream[_pendingCloseRequest];
432 } 502 }
433 503
434 function WritableStreamDefaultWriterGetDesiredSize(writer) { 504 function WritableStreamDefaultWriterGetDesiredSize(writer) {
435 const stream = writer[_ownerWritableStream]; 505 const stream = writer[_ownerWritableStream];
436 const state = stream[_state]; 506 const state = stream[_state];
437 if (state === ERRORED) { 507 if (state === ERRORED) {
438 return null; 508 return null;
439 } 509 }
440 if (state === CLOSED) { 510 if (state === CLOSED) {
441 return 0; 511 return 0;
442 } 512 }
443 return WritableStreamDefaultControllerGetDesiredSize( 513 return WritableStreamDefaultControllerGetDesiredSize(
444 stream[_writableStreamController]); 514 stream[_writableStreamController]);
445 } 515 }
446 516
447 function WritableStreamDefaultWriterRelease(writer) { 517 function WritableStreamDefaultWriterRelease(writer) {
448 const stream = writer[_ownerWritableStream]; 518 const stream = writer[_ownerWritableStream];
449 TEMP_ASSERT(stream !== undefined, 519 TEMP_ASSERT(stream !== undefined,
450 'stream is not undefined.'); 520 'stream is not undefined.');
451 TEMP_ASSERT(stream[_writer] === writer, 521 TEMP_ASSERT(stream[_writer] === writer,
452 'stream.[[writer]] is writer.'); 522 'stream.[[writer]] is writer.');
453 const releasedError = new TypeError(errReleasedWriterClosedPromise); 523 const releasedError = new TypeError(errReleasedWriterClosedPromise);
454 const state = stream[_state]; 524 const state = stream[_state];
455 if (state === WRITABLE || state === CLOSING) { 525 if (state === WRITABLE || state === CLOSING ||
526 stream[_pendingAbortRequest] !== undefined) {
456 v8.rejectPromise(writer[_closedPromise], releasedError); 527 v8.rejectPromise(writer[_closedPromise], releasedError);
457 } else { 528 } else {
458 writer[_closedPromise] = Promise_reject(releasedError); 529 writer[_closedPromise] = Promise_reject(releasedError);
459 } 530 }
531 v8.markPromiseAsHandled(writer[_closedPromise]);
532
460 if (state === WRITABLE && 533 if (state === WRITABLE &&
461 WritableStreamDefaultControllerGetBackpressure( 534 WritableStreamDefaultControllerGetBackpressure(
462 stream[_writableStreamController])) { 535 stream[_writableStreamController])) {
463 v8.rejectPromise(writer[_readyPromise], releasedError); 536 v8.rejectPromise(writer[_readyPromise], releasedError);
464 } else { 537 } else {
465 writer[_readyPromise] = Promise_reject(releasedError); 538 writer[_readyPromise] = Promise_reject(releasedError);
466 } 539 }
540 v8.markPromiseAsHandled(writer[_readyPromise]);
541
467 stream[_writer] = undefined; 542 stream[_writer] = undefined;
468 writer[_ownerWritableStream] = undefined; 543 writer[_ownerWritableStream] = undefined;
469 } 544 }
470 545
471 function WritableStreamDefaultWriterWrite(writer, chunk) { 546 function WritableStreamDefaultWriterWrite(writer, chunk) {
472 const stream = writer[_ownerWritableStream]; 547 const stream = writer[_ownerWritableStream];
473 TEMP_ASSERT(stream !== undefined, 548 TEMP_ASSERT(stream !== undefined,
474 'stream is not undefined.'); 549 'stream is not undefined.');
475 const state = stream[_state]; 550 const state = stream[_state];
476 if (state === CLOSED || state === ERRORED) { 551 if (state === CLOSED || state === ERRORED) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 function WritableStreamDefaultControllerGetDesiredSize(controller) { 628 function WritableStreamDefaultControllerGetDesiredSize(controller) {
554 const queueSize = GetTotalQueueSizeForController(controller); 629 const queueSize = GetTotalQueueSizeForController(controller);
555 return controller[_strategyHWM] - queueSize; 630 return controller[_strategyHWM] - queueSize;
556 } 631 }
557 632
558 function WritableStreamDefaultControllerWrite(controller, chunk) { 633 function WritableStreamDefaultControllerWrite(controller, chunk) {
559 const stream = controller[_controlledWritableStream]; 634 const stream = controller[_controlledWritableStream];
560 TEMP_ASSERT(stream[_state] === WRITABLE, 635 TEMP_ASSERT(stream[_state] === WRITABLE,
561 'stream.[[state]] is "writable".'); 636 'stream.[[state]] is "writable".');
562 let chunkSize = 1; 637 let chunkSize = 1;
563 if (controller[_strategySize] !== undefined) { 638 const strategySize = controller[_strategySize];
639 if (strategySize !== undefined) {
564 try { 640 try {
565 chunkSize = Function_call(controller[_strategySize], undefined, chunk); 641 chunkSize = strategySize(chunk);
566 } catch (e) { 642 } catch (e) {
567 WritableStreamDefaultControllerErrorIfNeeded(controller, e); 643 WritableStreamDefaultControllerErrorIfNeeded(controller, e);
568 return Promise_reject(e); 644 return;
569 } 645 }
570 } 646 }
571 const writeRecord = {chunk}; 647 const writeRecord = {chunk};
572 const lastBackpressure = 648 const lastBackpressure =
573 WritableStreamDefaultControllerGetBackpressure(controller); 649 WritableStreamDefaultControllerGetBackpressure(controller);
574 try { 650 try {
575 const enqueueResult = 651 EnqueueValueWithSizeForController(controller, writeRecord, chunkSize);
576 EnqueueValueWithSizeForController(controller, writeRecord, chunkSize);
577 } catch (e) { 652 } catch (e) {
578 WritableStreamDefaultControllerErrorIfNeeded(controller, e); 653 WritableStreamDefaultControllerErrorIfNeeded(controller, e);
579 return Promise_reject(e); 654 return;
580 } 655 }
581 if (stream[_state] === WRITABLE) { 656 if (stream[_state] === WRITABLE) {
582 const backpressure = 657 const backpressure =
583 WritableStreamDefaultControllerGetBackpressure(controller); 658 WritableStreamDefaultControllerGetBackpressure(controller);
584 if (lastBackpressure !== backpressure) { 659 if (lastBackpressure !== backpressure) {
585 WritableStreamUpdateBackpressure(stream, backpressure); 660 WritableStreamUpdateBackpressure(stream, backpressure);
586 } 661 }
587 } 662 }
588 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); 663 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
589 } 664 }
(...skipping 28 matching lines...) Expand all
618 } 693 }
619 } 694 }
620 695
621 function WritableStreamDefaultControllerProcessClose(controller) { 696 function WritableStreamDefaultControllerProcessClose(controller) {
622 const stream = controller[_controlledWritableStream]; 697 const stream = controller[_controlledWritableStream];
623 TEMP_ASSERT(stream[_state] === CLOSING, 698 TEMP_ASSERT(stream[_state] === CLOSING,
624 'stream.[[state]] is "closing".'); 699 'stream.[[state]] is "closing".');
625 DequeueValueForController(controller); 700 DequeueValueForController(controller);
626 TEMP_ASSERT(controller[_queue].length === 0, 701 TEMP_ASSERT(controller[_queue].length === 0,
627 'controller.[[queue]] is empty.'); 702 'controller.[[queue]] is empty.');
703 setDefaultControllerInCloseFlag(controller, true);
628 const sinkClosePromise = PromiseInvokeOrNoop(controller[_underlyingSink], 704 const sinkClosePromise = PromiseInvokeOrNoop(controller[_underlyingSink],
629 'close', [controller]); 705 'close', [controller]);
630 thenPromise(sinkClosePromise, 706 thenPromise(sinkClosePromise,
631 () => { 707 () => {
632 if (stream[_state] !== CLOSING) { 708 TEMP_ASSERT(getDefaultControllerInCloseFlag(controller)
709 === true,
710 'controller.[[inClose]] is true');
711 setDefaultControllerInCloseFlag(controller, false);
712
713 if (stream[_state] !== CLOSING &&
714 stream[_state] !== ERRORED) {
633 return; 715 return;
634 } 716 }
635 WritableStreamFulfillWriteRequest(stream); 717
718 TEMP_ASSERT(stream[_pendingCloseRequest] !== undefined);
719 v8.resolvePromise(stream[_pendingCloseRequest], undefined);
720 stream[_pendingCloseRequest] = undefined;
721
636 WritableStreamFinishClose(stream); 722 WritableStreamFinishClose(stream);
637 }, 723 },
638 r => WritableStreamDefaultControllerErrorIfNeeded(controller, r) 724 r => {
725 TEMP_ASSERT(getDefaultControllerInCloseFlag(controller)
726 === true,
727 'controller.[[inClose]] is true');
728 setDefaultControllerInCloseFlag(controller, false);
729
730 TEMP_ASSERT(stream[_pendingCloseRequest] !== undefined);
731 v8.rejectPromise(stream[_pendingCloseRequest], r);
732 stream[_pendingCloseRequest] = undefined;
733
734 if (stream[_pendingAbortRequest] !== undefined) {
735 v8.rejectPromise(stream[_pendingAbortRequest], r);
736 stream[_pendingAbortRequest] = undefined;
737 }
738
739 WritableStreamDefaultControllerErrorIfNeeded(controller, r);
740 }
639 ); 741 );
640 } 742 }
641 743
642 function WritableStreamDefaultControllerProcessWrite(controller, chunk) { 744 function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
643 setDefaultControllerWritingFlag(controller, true); 745 setDefaultControllerWritingFlag(controller, true);
746
747 const stream = controller[_controlledWritableStream];
748
749 TEMP_ASSERT(stream[_pendingWriteRequest] === undefined,
750 'stream.[[pendingWriteRequest]] is undefined');
751 TEMP_ASSERT(stream[_writeRequests].length > 0,
752 'stream.[[writeRequests]] is not empty');
753 stream[_pendingWriteRequest] = stream[_writeRequests].shift();
754
644 const sinkWritePromise = PromiseInvokeOrNoop(controller[_underlyingSink], 755 const sinkWritePromise = PromiseInvokeOrNoop(controller[_underlyingSink],
645 'write', [chunk, controller]); 756 'write', [chunk, controller]);
646 thenPromise( 757 thenPromise(
647 sinkWritePromise, 758 sinkWritePromise,
648 () => { 759 () => {
649 const stream = controller[_controlledWritableStream]; 760 TEMP_ASSERT(getDefaultControllerWritingFlag(controller) === true,
761 'controller.[[writing]] is true');
762 setDefaultControllerWritingFlag(controller, false);
763
764 TEMP_ASSERT(stream[_pendingWriteRequest] !== undefined,
765 'stream.[[pendingWriteRequest]] is not undefined');
766 v8.resolvePromise(stream[_pendingWriteRequest], undefined);
767 stream[_pendingWriteRequest] = undefined;
768
650 const state = stream[_state]; 769 const state = stream[_state];
651 if (state === ERRORED || state === CLOSED) { 770 if (state === ERRORED) {
771 WritableStreamRejectPromisesInReactionToError(stream);
772
773 if (stream[_pendingAbortRequest] !== undefined) {
774 v8.resolvePromise(stream[_pendingAbortRequest], undefined);
775 stream[_pendingAbortRequest] = undefined;
776 }
652 return; 777 return;
653 } 778 }
654 setDefaultControllerWritingFlag(controller, false); 779
655 WritableStreamFulfillWriteRequest(stream);
656 const lastBackpressure = 780 const lastBackpressure =
657 WritableStreamDefaultControllerGetBackpressure(controller); 781 WritableStreamDefaultControllerGetBackpressure(controller);
658 DequeueValueForController(controller); 782 DequeueValueForController(controller);
783
659 if (state !== CLOSING) { 784 if (state !== CLOSING) {
660 const backpressure = 785 const backpressure =
661 WritableStreamDefaultControllerGetBackpressure(controller); 786 WritableStreamDefaultControllerGetBackpressure(controller);
662 if (lastBackpressure !== backpressure) { 787 if (lastBackpressure !== backpressure) {
663 WritableStreamUpdateBackpressure( 788 WritableStreamUpdateBackpressure(
664 controller[_controlledWritableStream], backpressure); 789 controller[_controlledWritableStream], backpressure);
665 } 790 }
666 } 791 }
792
667 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); 793 WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
668 }, 794 },
669 r => WritableStreamDefaultControllerErrorIfNeeded(controller, r) 795 r => {
670 ); 796 TEMP_ASSERT(getDefaultControllerWritingFlag(controller) === true,
797 'controller.[[writing]] is true');
798 setDefaultControllerWritingFlag(controller, false);
799
800 TEMP_ASSERT(stream[_pendingWriteRequest] !== undefined,
801 'stream.[[pendingWriteRequest]] is not undefined');
802 v8.rejectPromise(stream[_pendingWriteRequest], r);
803 stream[_pendingWriteRequest] = undefined;
804
805 if (stream[_state] === ERRORED) {
806 stream[_storedError] = r;
807 WritableStreamRejectPromisesInReactionToError(stream);
808 }
809
810 if (stream[_pendingAbortRequest] !== undefined) {
811 v8.rejectPromise(stream[_pendingAbortRequest], r);
812 stream[_pendingAbortRequest] = undefined;
813 }
814
815 WritableStreamDefaultControllerErrorIfNeeded(controller, r);
816 }
817 );
671 } 818 }
672 819
673 function WritableStreamDefaultControllerGetBackpressure(controller) { 820 function WritableStreamDefaultControllerGetBackpressure(controller) {
674 const desiredSize = 821 const desiredSize =
675 WritableStreamDefaultControllerGetDesiredSize(controller); 822 WritableStreamDefaultControllerGetDesiredSize(controller);
676 return desiredSize <= 0; 823 return desiredSize <= 0;
677 } 824 }
678 825
679 function WritableStreamDefaultControllerError(controller, e) { 826 function WritableStreamDefaultControllerError(controller, e) {
680 const stream = controller[_controlledWritableStream]; 827 const stream = controller[_controlledWritableStream];
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 945
799 defineProperty(global, 'WritableStream', { 946 defineProperty(global, 'WritableStream', {
800 value: WritableStream, 947 value: WritableStream,
801 enumerable: false, 948 enumerable: false,
802 configurable: true, 949 configurable: true,
803 writable: true 950 writable: true
804 }); 951 });
805 952
806 // TODO(ricea): Exports to Blink 953 // TODO(ricea): Exports to Blink
807 }); 954 });
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/general.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698