summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/writable-streams/write.any.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/streams/writable-streams/write.any.js
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/streams/writable-streams/write.any.js')
-rw-r--r--testing/web-platform/tests/streams/writable-streams/write.any.js284
1 files changed, 284 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/writable-streams/write.any.js b/testing/web-platform/tests/streams/writable-streams/write.any.js
new file mode 100644
index 0000000000..f0246f6cad
--- /dev/null
+++ b/testing/web-platform/tests/streams/writable-streams/write.any.js
@@ -0,0 +1,284 @@
+// META: global=window,worker
+// META: script=../resources/test-utils.js
+// META: script=../resources/recording-streams.js
+'use strict';
+
+const error1 = new Error('error1');
+error1.name = 'error1';
+
+const error2 = new Error('error2');
+error2.name = 'error2';
+
+function writeArrayToStream(array, writableStreamWriter) {
+ array.forEach(chunk => writableStreamWriter.write(chunk));
+ return writableStreamWriter.close();
+}
+
+promise_test(() => {
+ let storage;
+ const ws = new WritableStream({
+ start() {
+ storage = [];
+ },
+
+ write(chunk) {
+ return delay(0).then(() => storage.push(chunk));
+ },
+
+ close() {
+ return delay(0);
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ const input = [1, 2, 3, 4, 5];
+ return writeArrayToStream(input, writer)
+ .then(() => assert_array_equals(storage, input, 'correct data should be relayed to underlying sink'));
+}, 'WritableStream should complete asynchronous writes before close resolves');
+
+promise_test(() => {
+ const ws = recordingWritableStream();
+
+ const writer = ws.getWriter();
+
+ const input = [1, 2, 3, 4, 5];
+ return writeArrayToStream(input, writer)
+ .then(() => assert_array_equals(ws.events, ['write', 1, 'write', 2, 'write', 3, 'write', 4, 'write', 5, 'close'],
+ 'correct data should be relayed to underlying sink'));
+}, 'WritableStream should complete synchronous writes before close resolves');
+
+promise_test(() => {
+ const ws = new WritableStream({
+ write() {
+ return 'Hello';
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ const writePromise = writer.write('a');
+ return writePromise
+ .then(value => assert_equals(value, undefined, 'fulfillment value must be undefined'));
+}, 'fulfillment value of ws.write() call should be undefined even if the underlying sink returns a non-undefined ' +
+ 'value');
+
+promise_test(() => {
+ let resolveSinkWritePromise;
+ const ws = new WritableStream({
+ write() {
+ return new Promise(resolve => {
+ resolveSinkWritePromise = resolve;
+ });
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
+
+ return writer.ready.then(() => {
+ const writePromise = writer.write('a');
+ let writePromiseResolved = false;
+ assert_not_equals(resolveSinkWritePromise, undefined, 'resolveSinkWritePromise should not be undefined');
+
+ assert_equals(writer.desiredSize, 0, 'desiredSize should be 0 after writer.write()');
+
+ return Promise.all([
+ writePromise.then(value => {
+ writePromiseResolved = true;
+ assert_equals(resolveSinkWritePromise, undefined, 'sinkWritePromise should be fulfilled before writePromise');
+
+ assert_equals(value, undefined, 'writePromise should be fulfilled with undefined');
+ }),
+ writer.ready.then(value => {
+ assert_equals(resolveSinkWritePromise, undefined, 'sinkWritePromise should be fulfilled before writer.ready');
+ assert_true(writePromiseResolved, 'writePromise should be fulfilled before writer.ready');
+
+ assert_equals(writer.desiredSize, 1, 'desiredSize should be 1 again');
+
+ assert_equals(value, undefined, 'writePromise should be fulfilled with undefined');
+ }),
+ flushAsyncEvents().then(() => {
+ resolveSinkWritePromise();
+ resolveSinkWritePromise = undefined;
+ })
+ ]);
+ });
+}, 'WritableStream should transition to waiting until write is acknowledged');
+
+promise_test(t => {
+ let sinkWritePromiseRejectors = [];
+ const ws = new WritableStream({
+ write() {
+ const sinkWritePromise = new Promise((r, reject) => sinkWritePromiseRejectors.push(reject));
+ return sinkWritePromise;
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
+
+ return writer.ready.then(() => {
+ const writePromise = writer.write('a');
+ assert_equals(sinkWritePromiseRejectors.length, 1, 'there should be 1 rejector');
+ assert_equals(writer.desiredSize, 0, 'desiredSize should be 0');
+
+ const writePromise2 = writer.write('b');
+ assert_equals(sinkWritePromiseRejectors.length, 1, 'there should be still 1 rejector');
+ assert_equals(writer.desiredSize, -1, 'desiredSize should be -1');
+
+ const closedPromise = writer.close();
+
+ assert_equals(writer.desiredSize, -1, 'desiredSize should still be -1');
+
+ return Promise.all([
+ promise_rejects_exactly(t, error1, closedPromise,
+ 'closedPromise should reject with the error returned from the sink\'s write method')
+ .then(() => assert_equals(sinkWritePromiseRejectors.length, 0,
+ 'sinkWritePromise should reject before closedPromise')),
+ promise_rejects_exactly(t, error1, writePromise,
+ 'writePromise should reject with the error returned from the sink\'s write method')
+ .then(() => assert_equals(sinkWritePromiseRejectors.length, 0,
+ 'sinkWritePromise should reject before writePromise')),
+ promise_rejects_exactly(t, error1, writePromise2,
+ 'writePromise2 should reject with the error returned from the sink\'s write method')
+ .then(() => assert_equals(sinkWritePromiseRejectors.length, 0,
+ 'sinkWritePromise should reject before writePromise2')),
+ flushAsyncEvents().then(() => {
+ sinkWritePromiseRejectors[0](error1);
+ sinkWritePromiseRejectors = [];
+ })
+ ]);
+ });
+}, 'when write returns a rejected promise, queued writes and close should be cleared');
+
+promise_test(t => {
+ const ws = new WritableStream({
+ write() {
+ throw error1;
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ return promise_rejects_exactly(t, error1, writer.write('a'),
+ 'write() should reject with the error returned from the sink\'s write method')
+ .then(() => promise_rejects_js(t, TypeError, writer.close(), 'close() should be rejected'));
+}, 'when sink\'s write throws an error, the stream should become errored and the promise should reject');
+
+promise_test(t => {
+ const ws = new WritableStream({
+ write(chunk, controller) {
+ controller.error(error1);
+ throw error2;
+ }
+ });
+
+ const writer = ws.getWriter();
+
+ return promise_rejects_exactly(t, error2, writer.write('a'),
+ 'write() should reject with the error returned from the sink\'s write method ')
+ .then(() => {
+ return Promise.all([
+ promise_rejects_exactly(t, error1, writer.ready,
+ 'writer.ready must reject with the error passed to the controller'),
+ promise_rejects_exactly(t, error1, writer.closed,
+ 'writer.closed must reject with the error passed to the controller')
+ ]);
+ });
+}, 'writer.write(), ready and closed reject with the error passed to controller.error() made before sink.write' +
+ ' rejection');
+
+promise_test(() => {
+ const numberOfWrites = 1000;
+
+ let resolveFirstWritePromise;
+ let writeCount = 0;
+ const ws = new WritableStream({
+ write() {
+ ++writeCount;
+ if (!resolveFirstWritePromise) {
+ return new Promise(resolve => {
+ resolveFirstWritePromise = resolve;
+ });
+ }
+ return Promise.resolve();
+ }
+ });
+
+ const writer = ws.getWriter();
+ return writer.ready.then(() => {
+ for (let i = 1; i < numberOfWrites; ++i) {
+ writer.write('a');
+ }
+ const writePromise = writer.write('a');
+
+ assert_equals(writeCount, 1, 'should have called sink\'s write once');
+
+ resolveFirstWritePromise();
+
+ return writePromise
+ .then(() =>
+ assert_equals(writeCount, numberOfWrites, `should have called sink's write ${numberOfWrites} times`));
+ });
+}, 'a large queue of writes should be processed completely');
+
+promise_test(() => {
+ const stream = recordingWritableStream();
+ const w = stream.getWriter();
+ const WritableStreamDefaultWriter = w.constructor;
+ w.releaseLock();
+ const writer = new WritableStreamDefaultWriter(stream);
+ return writer.ready.then(() => {
+ writer.write('a');
+ assert_array_equals(stream.events, ['write', 'a'], 'write() should be passed to sink');
+ });
+}, 'WritableStreamDefaultWriter should work when manually constructed');
+
+promise_test(() => {
+ let thenCalled = false;
+ const ws = new WritableStream({
+ write() {
+ return {
+ then(onFulfilled) {
+ thenCalled = true;
+ onFulfilled();
+ }
+ };
+ }
+ });
+ return ws.getWriter().write('a').then(() => assert_true(thenCalled, 'thenCalled should be true'));
+}, 'returning a thenable from write() should work');
+
+promise_test(() => {
+ const stream = new WritableStream();
+ const writer = stream.getWriter();
+ const WritableStreamDefaultWriter = writer.constructor;
+ assert_throws_js(TypeError, () => new WritableStreamDefaultWriter(stream),
+ 'should not be able to construct on locked stream');
+ // If stream.[[writer]] no longer points to |writer| then the closed Promise
+ // won't work properly.
+ return Promise.all([writer.close(), writer.closed]);
+}, 'failing DefaultWriter constructor should not release an existing writer');
+
+promise_test(t => {
+ const ws = new WritableStream({
+ start() {
+ return Promise.reject(error1);
+ }
+ }, { highWaterMark: 0 });
+ const writer = ws.getWriter();
+ return Promise.all([
+ promise_rejects_exactly(t, error1, writer.ready, 'ready should be rejected'),
+ promise_rejects_exactly(t, error1, writer.write(), 'write() should be rejected')
+ ]);
+}, 'write() on a stream with HWM 0 should not cause the ready Promise to resolve');
+
+promise_test(t => {
+ const ws = new WritableStream();
+ const writer = ws.getWriter();
+ writer.releaseLock();
+ return promise_rejects_js(t, TypeError, writer.write(), 'write should reject');
+}, 'writing to a released writer should reject the returned promise');