New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TransformStreamDefaultController terminate() method #818
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>terminate.js browser context wrapper file</title> | ||
|
||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
|
||
<script src="../resources/test-utils.js"></script> | ||
<script src="../resources/recording-streams.js"></script> | ||
|
||
<script src="terminate.js"></script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
'use strict'; | ||
|
||
if (self.importScripts) { | ||
self.importScripts('/resources/testharness.js'); | ||
self.importScripts('../resources/recording-streams.js'); | ||
self.importScripts('../resources/test-utils.js'); | ||
} | ||
|
||
promise_test(t => { | ||
const ts = recordingTransformStream({}, undefined, { highWaterMark: 0 }); | ||
const rs = new ReadableStream({ | ||
start(controller) { | ||
controller.enqueue(0); | ||
} | ||
}); | ||
let pipeToRejected = false; | ||
const pipeToPromise = promise_rejects(t, new TypeError(), rs.pipeTo(ts.writable), 'pipeTo should reject').then(() => { | ||
pipeToRejected = true; | ||
}); | ||
return delay(0).then(() => { | ||
assert_array_equals(ts.events, [], 'transform() should have seen no chunks'); | ||
assert_false(pipeToRejected, 'pipeTo() should not have rejected yet'); | ||
ts.controller.terminate(); | ||
return pipeToPromise; | ||
}).then(() => { | ||
assert_array_equals(ts.events, [], 'transform() should still have seen no chunks'); | ||
assert_true(pipeToRejected, 'pipeToRejected must be true'); | ||
}); | ||
}, 'controller.terminate() should error pipeTo()'); | ||
|
||
promise_test(t => { | ||
const ts = recordingTransformStream({}, undefined, { highWaterMark: 1 }); | ||
const rs = new ReadableStream({ | ||
start(controller) { | ||
controller.enqueue(0); | ||
controller.enqueue(1); | ||
} | ||
}); | ||
const pipeToPromise = rs.pipeTo(ts.writable); | ||
return delay(0).then(() => { | ||
assert_array_equals(ts.events, ['transform', 0], 'transform() should have seen one chunk'); | ||
ts.controller.terminate(); | ||
return promise_rejects(t, new TypeError(), pipeToPromise, 'pipeTo() should reject'); | ||
}).then(() => { | ||
assert_array_equals(ts.events, ['transform', 0], 'transform() should still have seen only one chunk'); | ||
}); | ||
}, 'controller.terminate() should prevent remaining chunks from being processed'); | ||
|
||
test(() => { | ||
new TransformStream({ | ||
start(controller) { | ||
controller.enqueue(0); | ||
controller.terminate(); | ||
assert_throws(new TypeError(), () => controller.enqueue(1), 'enqueue should throw'); | ||
} | ||
}); | ||
}, 'controller.enqueue() should throw after controller.terminate()'); | ||
|
||
const error1 = new Error('error1'); | ||
error1.name = 'error1'; | ||
|
||
promise_test(t => { | ||
const ts = new TransformStream({ | ||
start(controller) { | ||
controller.enqueue(0); | ||
controller.terminate(); | ||
controller.error(error1); | ||
} | ||
}); | ||
return Promise.all([ | ||
promise_rejects(t, new TypeError(), ts.writable.abort(), 'abort() should reject with a TypeError'), | ||
promise_rejects(t, error1, ts.readable.cancel(), 'cancel() should reject with error1') | ||
]); | ||
}, 'controller.error() after controller.terminate() with queued chunk should error the readable'); | ||
|
||
test(() => { | ||
new TransformStream({ | ||
start(controller) { | ||
controller.terminate(); | ||
assert_throws(new TypeError(), () => controller.error(error1), 'error() should throw'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened #821. In general, have we tested/are we OK with the behavior for when controller methods throw? I think a guiding principle is that you shouldn't throw if it's not "your fault", e.g. if someone using the public API of the stream can transition the state in some way as to cause an exception. Does that sound familiar from previous discussions? Are we following it here, e.g. if the writable side is aborted or the readable side canceled? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for bringing this up. I had forgotten about it actually. I filed #822 to track the changes to transform stream. |
||
} | ||
}); | ||
}, 'controller.error() after controller.terminate() without queued chunk should throw'); | ||
|
||
done(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we test more than .cancel() to test if it's errored properly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.cancel() is actually pretty specific. I added reader.closed to the tests just to be sure. I don't want to get into testing Readablestream itself here.