diff --git a/index.bs b/index.bs index e17dabace..6482838bd 100644 --- a/index.bs +++ b/index.bs @@ -3167,7 +3167,8 @@ nothrow>WritableStreamDefaultWriterRelease ( writer ) 1. Assert: _stream_.[[writer]] is _writer_. 1. Let _releasedError_ be a new *TypeError*. 1. Let _state_ be _stream_.[[state]]. - 1. If _state_ is `"writable"` or `"closing"`, reject _writer_.[[closedPromise]] with _releasedError_. + 1. If _state_ is `"writable"` or `"closing"`, or _stream_.[[pendingAbortRequest]] is not *undefined*, reject + _writer_.[[closedPromise]] with _releasedError_. 1. Otherwise, set _writer_.[[closedPromise]] to a promise rejected with _releasedError_. 1. Set _writer_.[[closedPromise]].[[PromiseIsHandled]] to *true*. 1. If _state_ is `"writable"` and ! diff --git a/reference-implementation/lib/writable-stream.js b/reference-implementation/lib/writable-stream.js index 47a4a27ee..e7fbf0bc1 100644 --- a/reference-implementation/lib/writable-stream.js +++ b/reference-implementation/lib/writable-stream.js @@ -471,7 +471,7 @@ function WritableStreamDefaultWriterRelease(writer) { 'Writer was released and can no longer be used to monitor the stream\'s closedness'); const state = stream._state; - if (state === 'writable' || state === 'closing') { + if (state === 'writable' || state === 'closing' || stream._pendingAbortRequest !== undefined) { defaultWriterClosedPromiseReject(writer, releasedError); } else { defaultWriterClosedPromiseResetToRejected(writer, releasedError); diff --git a/reference-implementation/to-upstream-wpts/writable-streams/aborting.js b/reference-implementation/to-upstream-wpts/writable-streams/aborting.js index cbb5228cb..a48fe2b34 100644 --- a/reference-implementation/to-upstream-wpts/writable-streams/aborting.js +++ b/reference-implementation/to-upstream-wpts/writable-streams/aborting.js @@ -467,4 +467,66 @@ promise_test(t => { }); }, 'writer.ready should reject on controller error without waiting for underlying write'); +promise_test(t => { + let resolveWrite; + const ws = new WritableStream({ + write() { + return new Promise(resolve => { + resolveWrite = resolve; + }); + } + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise = writer.write('a'); + const closed = writer.closed; + const abortPromise = writer.abort(); + writer.releaseLock(); + resolveWrite(); + return Promise.all([ + writePromise, + abortPromise, + promise_rejects(t, new TypeError(), closed, 'closed should reject')]); + }); +}, 'releaseLock() while aborting should reject the original closed promise'); + +promise_test(t => { + let resolveWrite; + let resolveAbort; + let resolveAbortStarted; + const abortStarted = new Promise(resolve => { + resolveAbortStarted = resolve; + }); + const ws = new WritableStream({ + write() { + return new Promise(resolve => { + resolveWrite = resolve; + }); + }, + abort() { + resolveAbortStarted(); + return new Promise(resolve => { + resolveAbort = resolve; + }); + } + }); + const writer = ws.getWriter(); + return writer.ready.then(() => { + const writePromise = writer.write('a'); + const closed = writer.closed; + const abortPromise = writer.abort(); + resolveWrite(); + return abortStarted.then(() => { + writer.releaseLock(); + assert_not_equals(writer.closed, closed, 'closed promise should have changed'); + resolveAbort(); + return Promise.all([ + writePromise, + abortPromise, + promise_rejects(t, new TypeError(), closed, 'original closed should reject'), + promise_rejects(t, new TypeError(), writer.closed, 'new closed should reject')]); + }); + }); +}, 'releaseLock() during delayed async abort() should create a new rejected closed promise'); + done();