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

Unified Diff: third_party/WebKit/Source/core/streams/WritableStream.js

Issue 2823563002: Unified error handling for WritableStream (Closed)
Patch Set: remove local copy of piping/multiple-propagation test as it is fail Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https-expected.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/streams/WritableStream.js
diff --git a/third_party/WebKit/Source/core/streams/WritableStream.js b/third_party/WebKit/Source/core/streams/WritableStream.js
index 4a4429cba4265467df633a4571b661315efbae27..7be92669bb958edce729ae73188e180043654881 100644
--- a/third_party/WebKit/Source/core/streams/WritableStream.js
+++ b/third_party/WebKit/Source/core/streams/WritableStream.js
@@ -41,14 +41,16 @@
const _strategySize = v8.createPrivateSymbol('[[strategySize]]');
const _underlyingSink = v8.createPrivateSymbol('[[underlyingSink]]');
- // Numeric encodings of states
+ // Numeric encodings of stream states. Stored in the _stateAndFlags slot.
const WRITABLE = 0;
const CLOSED = 1;
- const ERRORED = 2;
+ const ERRORING = 2;
+ const ERRORED = 3;
- // Mask to extract or assign states to _stateAndFlags
+ // Mask to extract or assign states to _stateAndFlags.
const STATE_MASK = 0xF;
+ // Also stored in _stateAndFlags.
const BACKPRESSURE_FLAG = 0x10;
// Javascript functions. It is important to use these copies, as the ones on
@@ -206,48 +208,26 @@
if (state === ERRORED) {
return Promise_reject(stream[_storedError]);
}
- TEMP_ASSERT(state === WRITABLE,
- 'state is "writable".');
const error = new TypeError(errStreamAborting);
if (stream[_pendingAbortRequest] !== undefined) {
return Promise_reject(error);
}
- const controller = stream[_writableStreamController];
- TEMP_ASSERT(controller !== undefined,
- 'controller is not undefined');
- if (!WritableStreamHasOperationMarkedInFlight(stream) &&
- controller[_started]) {
- WritableStreamFinishAbort(stream);
- return WritableStreamDefaultControllerAbortSteps(controller, reason);
- }
- const writer = stream[_writer];
- if (writer !== undefined) {
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error);
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_state_ is `"writable"` or `"erroring"`');
+
+ const wasAlreadyErroring = state === ERRORING;
+ if (wasAlreadyErroring) {
+ reason = undefined;
}
+
const promise = v8.createPromise();
- stream[_pendingAbortRequest] = {promise, reason};
- return promise;
- }
+ stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring};
- function WritableStreamError(stream, error) {
- stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
- stream[_storedError] = error;
- WritableStreamDefaultControllerErrorSteps(stream[_writableStreamController]);
- if (stream[_pendingAbortRequest] === undefined) {
- const writer = stream[_writer];
- if (writer !== undefined) {
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error);
- }
- }
- if (!WritableStreamHasOperationMarkedInFlight(stream)) {
- WritableStreamRejectPromisesInReactionToError(stream);
+ if (!wasAlreadyErroring) {
+ WritableStreamStartErroring(stream, error);
}
- }
-
- function WritableStreamFinishAbort(stream) {
- const error = new TypeError(errStreamAborted);
- WritableStreamError(stream, error);
+ return promise;
}
// Writable Stream Abstract Operations Used by Controllers
@@ -262,23 +242,90 @@
return promise;
}
- function WritableStreamFinishInFlightWrite(stream) {
- TEMP_ASSERT(stream[_inFlightWriteRequest] !== undefined,
- '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
- v8.resolvePromise(stream[_inFlightWriteRequest], undefined);
- stream[_inFlightWriteRequest] = undefined;
+ function WritableStreamDealWithRejection(stream, error) {
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- WritableStreamFinishInFlightWriteInErroredState(stream);
+ if (state === WRITABLE) {
+ WritableStreamStartErroring(stream, error);
+ return;
+ }
+
+ TEMP_ASSERT(state === ERRORING, '_state_ is `"erroring"`');
+ WritableStreamFinishErroring(stream);
+ }
+
+ function WritableStreamStartErroring(stream, reason) {
+ TEMP_ASSERT(stream[_storedError] === undefined,
+ '_stream_.[[storedError]] is *undefined*');
+ TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
+ '_stream_.[[state]] is `"writable"`');
+
+ const controller = stream[_writableStreamController];
+ TEMP_ASSERT(controller !== undefined, '_controller_ is not *undefined*');
+
+ stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORING;
+ stream[_storedError] = reason;
+
+ const writer = stream[_writer];
+ if (writer !== undefined) {
+ WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
+ }
+
+ if (!WritableStreamHasOperationMarkedInFlight(stream) &&
+ controller[_started]) {
+ WritableStreamFinishErroring(stream);
+ }
+ }
+
+ function WritableStreamFinishErroring(stream) {
+ TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === ERRORING,
+ '_stream_.[[state]] is `"erroring"`');
+ TEMP_ASSERT(
+ !WritableStreamHasOperationMarkedInFlight(stream),
+ '! WritableStreamHasOperationMarkedInFlight(_stream_) is *false*');
+
+ stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
+
+ WritableStreamDefaultControllerErrorSteps(
+ stream[_writableStreamController]);
+
+ const storedError = stream[_storedError];
+ rejectPromises(stream[_writeRequests], storedError);
+ stream[_writeRequests] = new binding.SimpleQueue();
+
+ if (stream[_pendingAbortRequest] === undefined) {
+ WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+ return;
+ }
+
+ const abortRequest = stream[_pendingAbortRequest];
+ stream[_pendingAbortRequest] = undefined;
+
+ if (abortRequest.wasAlreadyErroring === true) {
+ v8.rejectPromise(abortRequest.promise, storedError);
+ WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
return;
}
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
- WritableStreamHandleAbortRequestIfPending(stream);
+
+ const promise = WritableStreamDefaultControllerAbortSteps(
+ stream[_writableStreamController], abortRequest.reason);
+
+ thenPromise(
+ promise,
+ () => {
+ v8.resolvePromise(abortRequest.promise, undefined);
+ WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+ },
+ reason => {
+ v8.rejectPromise(abortRequest.promise, reason);
+ WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+ });
}
- function WritableStreamFinishInFlightWriteInErroredState(stream) {
- WritableStreamRejectAbortRequestIfPending(stream);
- WritableStreamRejectPromisesInReactionToError(stream);
+ function WritableStreamFinishInFlightWrite(stream) {
+ TEMP_ASSERT(stream[_inFlightWriteRequest] !== undefined,
+ '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
+ v8.resolvePromise(stream[_inFlightWriteRequest], undefined);
+ stream[_inFlightWriteRequest] = undefined;
}
function WritableStreamFinishInFlightWriteWithError(stream, error) {
@@ -286,14 +333,12 @@
'_stream_.[[inFlightWriteRequest]] is not *undefined*.');
v8.rejectPromise(stream[_inFlightWriteRequest], error);
stream[_inFlightWriteRequest] = undefined;
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- WritableStreamFinishInFlightWriteInErroredState(stream);
- return;
- }
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
- WritableStreamError(stream, error);
- WritableStreamRejectAbortRequestIfPending(stream);
+
+ let state = stream[_stateAndFlags] & STATE_MASK;
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+ WritableStreamDealWithRejection(stream, error);
}
function WritableStreamFinishInFlightClose(stream) {
@@ -301,26 +346,29 @@
'_stream_.[[inFlightCloseRequest]] is not *undefined*.');
v8.resolvePromise(stream[_inFlightCloseRequest], undefined);
stream[_inFlightCloseRequest] = undefined;
+
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- WritableStreamFinishInFlightCloseInErroredState(stream);
- return;
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+ if (state === ERRORING) {
+ stream[_storedError] = undefined;
+ if (stream[_pendingAbortRequest] !== undefined) {
+ v8.resolvePromise(stream[_pendingAbortRequest].promise, undefined);
+ stream[_pendingAbortRequest] = undefined;
+ }
}
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
+
stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | CLOSED;
const writer = stream[_writer];
if (writer !== undefined) {
v8.resolvePromise(writer[_closedPromise], undefined);
}
- if (stream[_pendingAbortRequest] !== undefined) {
- v8.resolvePromise(stream[_pendingAbortRequest].promise, undefined);
- stream[_pendingAbortRequest] = undefined;
- }
- }
- function WritableStreamFinishInFlightCloseInErroredState(stream) {
- WritableStreamRejectAbortRequestIfPending(stream);
- WritableStreamRejectClosedPromiseInReactionToError(stream);
+ TEMP_ASSERT(stream[_pendingAbortRequest] === undefined,
+ '_stream_.[[pendingAbortRequest]] is *undefined*');
+ TEMP_ASSERT(stream[_storedError] === undefined,
+ '_stream_.[[storedError]] is *undefined*');
}
function WritableStreamFinishInFlightCloseWithError(stream, error) {
@@ -328,14 +376,17 @@
'_stream_.[[inFlightCloseRequest]] is not *undefined*.');
v8.rejectPromise(stream[_inFlightCloseRequest], error);
stream[_inFlightCloseRequest] = undefined;
+
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- WritableStreamFinishInFlightCloseInErroredState(stream);
- return;
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+ if (stream[_pendingAbortRequest] !== undefined) {
+ v8.rejectPromise(stream[_pendingAbortRequest].promise, error);
+ stream[_pendingAbortRequest] = undefined;
}
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
- WritableStreamError(stream, error);
- WritableStreamRejectAbortRequestIfPending(stream);
+
+ WritableStreamDealWithRejection(stream, error);
}
function WritableStreamCloseQueuedOrInFlight(stream) {
@@ -343,21 +394,6 @@
stream[_inFlightCloseRequest] !== undefined;
}
- function WritableStreamHandleAbortRequestIfPending(stream) {
- if (stream[_pendingAbortRequest] === undefined) {
- return;
- }
- WritableStreamFinishAbort(stream);
- const abortRequest = stream[_pendingAbortRequest];
- stream[_pendingAbortRequest] = undefined;
- const promise =
- WritableStreamDefaultControllerAbortSteps(stream[_writableStreamController],
- abortRequest.reason);
- thenPromise(promise,
- result => v8.resolvePromise(abortRequest.promise, result),
- reason => v8.rejectPromise(abortRequest.promise, reason));
- }
-
function WritableStreamHasOperationMarkedInFlight(stream) {
return stream[_inFlightWriteRequest] !== undefined ||
stream[_inFlightCloseRequest] !== undefined;
@@ -381,35 +417,22 @@
stream[_inFlightWriteRequest] = writeRequest;
}
- function WritableStreamRejectClosedPromiseInReactionToError(stream) {
- const writer = stream[_writer];
- if (writer !== undefined) {
- v8.rejectPromise(writer[_closedPromise], stream[_storedError]);
- v8.markPromiseAsHandled(writer[_closedPromise]);
- }
- }
-
- function WritableStreamRejectAbortRequestIfPending(stream) {
- if (stream[_pendingAbortRequest] !== undefined) {
- v8.rejectPromise(stream[_pendingAbortRequest].promise,
- stream[_storedError]);
- stream[_pendingAbortRequest] = undefined;
- }
- }
-
- function WritableStreamRejectPromisesInReactionToError(stream) {
- const storedError = stream[_storedError];
- rejectPromises(stream[_writeRequests], storedError);
- stream[_writeRequests] = new binding.SimpleQueue();
+ function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
+ TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === ERRORED,
+ '_stream_.[[state]] is `"errored"`');
if (stream[_closeRequest] !== undefined) {
TEMP_ASSERT(stream[_inFlightCloseRequest] === undefined,
- '_stream_.[[inFlightCloseRequest]] is *undefined*.');
- v8.rejectPromise(stream[_closeRequest], storedError);
+ '_stream_.[[inFlightCloseRequest]] is *undefined*');
+ v8.rejectPromise(stream[_closeRequest], stream[_storedError]);
stream[_closeRequest] = undefined;
}
- WritableStreamRejectClosedPromiseInReactionToError(stream);
+ const writer = stream[_writer];
+ if (writer !== undefined) {
+ v8.rejectPromise(writer[_closedPromise], stream[_storedError]);
+ v8.markPromiseAsHandled(writer[_closedPromise]);
+ }
}
function WritableStreamUpdateBackpressure(stream, backpressure) {
@@ -466,28 +489,44 @@
this[_ownerWritableStream] = stream;
stream[_writer] = this;
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === WRITABLE) {
- if (stream[_pendingAbortRequest] !== undefined) {
- const error = new TypeError(errStreamAborting);
- this[_readyPromise] = Promise_reject(error);
+ switch (state) {
+ case WRITABLE:
+ {
+ if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+ stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
+ this[_readyPromise] = v8.createPromise();
+ } else {
+ this[_readyPromise] = Promise_resolve(undefined);
+ }
+ this[_closedPromise] = v8.createPromise();
+ break;
+ }
+
+ case ERRORING:
+ {
+ this[_readyPromise] = Promise_reject(stream[_storedError]);
v8.markPromiseAsHandled(this[_readyPromise]);
- } else if (!WritableStreamCloseQueuedOrInFlight(stream) &&
- stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
- this[_readyPromise] = v8.createPromise();
- } else {
+ this[_closedPromise] = v8.createPromise();
+ break;
+ }
+
+ case CLOSED:
+ {
this[_readyPromise] = Promise_resolve(undefined);
+ this[_closedPromise] = Promise_resolve(undefined);
+ break;
+ }
+
+ default:
+ {
+ TEMP_ASSERT(state === ERRORED, '_state_ is `"errored"`.');
+ const storedError = stream[_storedError];
+ this[_readyPromise] = Promise_reject(storedError);
+ v8.markPromiseAsHandled(this[_readyPromise]);
+ this[_closedPromise] = Promise_reject(storedError);
+ v8.markPromiseAsHandled(this[_closedPromise]);
+ break;
}
- this[_closedPromise] = v8.createPromise();
- } else if (state === CLOSED) {
- this[_readyPromise] = Promise_resolve(undefined);
- this[_closedPromise] = Promise_resolve(undefined);
- } else {
- TEMP_ASSERT(state === ERRORED, '_state_ is `"errored"`.');
- const storedError = stream[_storedError];
- this[_readyPromise] = Promise_reject(storedError);
- v8.markPromiseAsHandled(this[_readyPromise]);
- this[_closedPromise] = Promise_reject(storedError);
- v8.markPromiseAsHandled(this[_closedPromise]);
}
}
@@ -584,15 +623,16 @@
return Promise_reject(
createCannotActionOnStateStreamError('close', state));
}
- if (stream[_pendingAbortRequest] !== undefined) {
- return Promise_reject(new TypeError(errStreamAborting));
- }
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
+
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_state_ is `"writable"` or `"erroring"`.');
TEMP_ASSERT(!WritableStreamCloseQueuedOrInFlight(stream),
'! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
const promise = v8.createPromise();
stream[_closeRequest] = promise;
- if (stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
+
+ if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) &&
+ state === WRITABLE) {
v8.resolvePromise(writer[_readyPromise], undefined);
}
WritableStreamDefaultControllerClose(stream[_writableStreamController]);
@@ -609,12 +649,26 @@
if (state === ERRORED) {
return Promise_reject(stream[_storedError]);
}
- TEMP_ASSERT(state === WRITABLE, 'state is "writable".');
+
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_state_ is `"writable"` or `"erroring"`.');
+
return WritableStreamDefaultWriterClose(writer);
}
- function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer,
- error) {
+ function WritableStreamDefaultWriterEnsureClosedPromiseRejected(
+ writer, error) {
+ if (v8.promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) {
+ v8.rejectPromise(writer[_closedPromise], error);
+ } else {
+ writer[_closedPromise] = Promise_reject(error);
+ }
+ v8.markPromiseAsHandled(writer[_closedPromise]);
+ }
+
+
+ function WritableStreamDefaultWriterEnsureReadyPromiseRejected(
+ writer, error) {
if (v8.promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) {
v8.rejectPromise(writer[_readyPromise], error);
} else {
@@ -626,7 +680,7 @@
function WritableStreamDefaultWriterGetDesiredSize(writer) {
const stream = writer[_ownerWritableStream];
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED || stream[_pendingAbortRequest] !== undefined) {
+ if (state === ERRORED || state === ERRORING) {
return null;
}
if (state === CLOSED) {
@@ -643,16 +697,10 @@
TEMP_ASSERT(stream[_writer] === writer,
'stream.[[writer]] is writer.');
const releasedError = new TypeError(errReleasedWriterClosedPromise);
- const state = stream[_stateAndFlags] & STATE_MASK;
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer,
- releasedError);
- if (state === WRITABLE ||
- WritableStreamHasOperationMarkedInFlight(stream)) {
- v8.rejectPromise(writer[_closedPromise], releasedError);
- } else {
- writer[_closedPromise] = Promise_reject(releasedError);
- }
- v8.markPromiseAsHandled(writer[_closedPromise]);
+ WritableStreamDefaultWriterEnsureReadyPromiseRejected(
+ writer, releasedError);
+ WritableStreamDefaultWriterEnsureClosedPromiseRejected(
+ writer, releasedError);
stream[_writer] = undefined;
writer[_ownerWritableStream] = undefined;
}
@@ -678,9 +726,10 @@
return Promise_reject(
createCannotActionOnStateStreamError('write to', CLOSED));
}
- if (stream[_pendingAbortRequest] !== undefined) {
- return Promise_reject(new TypeError(errStreamAborting));
+ if (state === ERRORING) {
+ return Promise_reject(stream[_storedError]);
}
+ TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`');
const promise = WritableStreamAddWriteRequest(stream);
WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
return promise;
@@ -730,9 +779,10 @@
if (!IsWritableStreamDefaultController(this)) {
throw new TypeError(streamErrors.illegalInvocation);
}
- const state = this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
- if (state === CLOSED || state === ERRORED) {
- throw createCannotActionOnStateStreamError('error', state);
+ const state =
+ this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
+ if (state !== WRITABLE) {
+ return;
}
WritableStreamDefaultControllerError(this, e);
}
@@ -744,9 +794,7 @@
// or impossible, so use static dispatch for now. This will have to be fixed
// when adding a byte controller.
function WritableStreamDefaultControllerAbortSteps(controller, reason) {
- const sinkAbortPromise =
- PromiseInvokeOrNoop(controller[_underlyingSink], 'abort', [reason]);
- return thenPromise(sinkAbortPromise, () => undefined);
+ return PromiseInvokeOrNoop(controller[_underlyingSink], 'abort', [reason]);
}
function WritableStreamDefaultControllerErrorSteps(controller) {
@@ -761,21 +809,18 @@
thenPromise(
startPromise,
() => {
+ const state = stream[_stateAndFlags] & STATE_MASK;
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_stream_.[[state]] is `"writable"` or `"erroring"`');
controller[_started] = true;
- if ((stream[_stateAndFlags] & STATE_MASK) === ERRORED) {
- WritableStreamRejectAbortRequestIfPending(stream);
- } else {
- WritableStreamHandleAbortRequestIfPending(stream);
- }
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
},
r => {
- TEMP_ASSERT(
- (stream[_stateAndFlags] & STATE_MASK) === WRITABLE ||
- (stream[_stateAndFlags] & STATE_MASK) === ERRORED,
- '_stream_.[[state]] is `"writable"` or `"errored"`.');
- WritableStreamDefaultControllerErrorIfNeeded(controller, r);
- WritableStreamRejectAbortRequestIfPending(stream);
+ const state = stream[_stateAndFlags] & STATE_MASK;
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_stream_.[[state]] is `"writable"` or `"erroring"`');
+ controller[_started] = true;
+ WritableStreamDealWithRejection(stream, r);
});
}
@@ -818,7 +863,8 @@
return;
}
const stream = controller[_controlledWritableStream];
- if (!WritableStreamCloseQueuedOrInFlight(stream)) {
+ if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+ (stream[_stateAndFlags] & STATE_MASK) === WRITABLE) {
const backpressure =
WritableStreamDefaultControllerGetBackpressure(controller);
WritableStreamUpdateBackpressure(stream, backpressure);
@@ -828,16 +874,20 @@
function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
const stream = controller[_controlledWritableStream];
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === CLOSED || state === ERRORED) {
- return;
- }
if (!controller[_started]) {
return;
}
if (stream[_inFlightWriteRequest] !== undefined) {
return;
}
+ const state = stream[_stateAndFlags] & STATE_MASK;
+ if (state === CLOSED || state === ERRORED) {
+ return;
+ }
+ if (state === ERRORING) {
+ WritableStreamFinishErroring(stream);
+ return;
+ }
if (controller[_queue].length === 0) {
return;
}
@@ -851,7 +901,8 @@
}
function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
- const state = controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
+ const state =
+ controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
if (state === WRITABLE) {
WritableStreamDefaultControllerError(controller, error);
}
@@ -863,8 +914,8 @@
DequeueValue(controller);
TEMP_ASSERT(controller[_queue].length === 0,
'controller.[[queue]] is empty.');
- const sinkClosePromise = PromiseInvokeOrNoop(controller[_underlyingSink],
- 'close', [controller]);
+ const sinkClosePromise = PromiseInvokeOrNoop(
+ controller[_underlyingSink], 'close', []);
thenPromise(
sinkClosePromise,
() => WritableStreamFinishInFlightClose(stream),
@@ -882,12 +933,11 @@
() => {
WritableStreamFinishInFlightWrite(stream);
const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- return;
- }
- TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
+ TEMP_ASSERT(state === WRITABLE || state === ERRORING,
+ '_state_ is `"writable"` or `"erroring"`');
DequeueValue(controller);
- if (!WritableStreamCloseQueuedOrInFlight(stream)) {
+ if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+ state === WRITABLE) {
const backpressure =
WritableStreamDefaultControllerGetBackpressure(controller);
WritableStreamUpdateBackpressure(stream, backpressure);
@@ -895,13 +945,7 @@
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
},
reason => {
- const wasErrored = (stream[_stateAndFlags] & STATE_MASK) === ERRORED;
WritableStreamFinishInFlightWriteWithError(stream, reason);
- TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === ERRORED,
- '_stream_.[[state]] is `"errored"`.');
- if (!wasErrored) {
- ResetQueue(controller);
- }
});
}
@@ -915,7 +959,7 @@
const stream = controller[_controlledWritableStream];
TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
'_stream_.[[state]] is `"writable"`.');
- WritableStreamError(stream, error);
+ WritableStreamStartErroring(stream, error);
}
// Queue-with-Sizes Operations
« no previous file with comments | « third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698