From e632d6460c7150c4c77a5224938605f84383b95e Mon Sep 17 00:00:00 2001 From: Adam Rice Date: Fri, 15 Sep 2017 22:57:37 +0900 Subject: [PATCH] Detect if the TransformStream errored inside write() and reject If a TransformStream errored while the TransformStreamDefaultSink write() method was waiting for backpressure to be relieved, it would assert inside the TransformStreamStream operation. Since it is not useful to call transform() once the stream is errored, return a rejection from the write() method instead. Also add a test for this case. --- .../lib/transform-stream.js | 7 ++++- .../transform-streams/errors.js | 26 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/reference-implementation/lib/transform-stream.js b/reference-implementation/lib/transform-stream.js index 26370769e..0a2d61889 100644 --- a/reference-implementation/lib/transform-stream.js +++ b/reference-implementation/lib/transform-stream.js @@ -318,7 +318,12 @@ class TransformStreamDefaultSink { if (transformStream._backpressure === true) { return transformStream._backpressureChangePromise - .then(() => TransformStreamTransform(transformStream, chunk)); + .then(() => { + if (transformStream._errored === true) { + return Promise.reject(transformStream._storedError); + } + return TransformStreamTransform(transformStream, chunk); + }); } return TransformStreamTransform(transformStream, chunk); diff --git a/reference-implementation/to-upstream-wpts/transform-streams/errors.js b/reference-implementation/to-upstream-wpts/transform-streams/errors.js index bbbd8b8a8..8c72adc73 100644 --- a/reference-implementation/to-upstream-wpts/transform-streams/errors.js +++ b/reference-implementation/to-upstream-wpts/transform-streams/errors.js @@ -282,4 +282,30 @@ promise_test(t => { }); }, 'controller.error() should throw after a transformer method has thrown an exception'); +promise_test(t => { + let controller; + let calls = 0; + const ts = new TransformStream({ + start(c) { + controller = c; + }, + transform() { + ++calls; + } + }, undefined, { highWaterMark: 1 }); + return delay(0).then(() => { + // Create backpressure. + controller.enqueue('a'); + const writer = ts.writable.getWriter(); + // transform() will not be called until backpressure is relieved. + const writePromise = writer.write('b'); + assert_equals(calls, 0, 'transform() should not have been called'); + controller.error(thrownError); + // Now backpressure has been relieved and the write can proceed. + return promise_rejects(t, thrownError, writePromise, 'write() should reject').then(() => { + assert_equals(calls, 0, 'transform() should not be called'); + }); + }); +}, 'erroring during write with backpressure should result in the write failing'); + done();