11cb0ef41Sopenharmony_ci// META: global=window,worker 21cb0ef41Sopenharmony_ci// META: script=../resources/recording-streams.js 31cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js 41cb0ef41Sopenharmony_ci'use strict'; 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst error1 = new Error('error1 message'); 71cb0ef41Sopenharmony_cierror1.name = 'error1'; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_cipromise_test(() => { 101cb0ef41Sopenharmony_ci const ts = recordingTransformStream(); 111cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 121cb0ef41Sopenharmony_ci // This call never resolves. 131cb0ef41Sopenharmony_ci writer.write('a'); 141cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 151cb0ef41Sopenharmony_ci assert_array_equals(ts.events, [], 'transform should not be called'); 161cb0ef41Sopenharmony_ci }); 171cb0ef41Sopenharmony_ci}, 'backpressure allows no transforms with a default identity transform and no reader'); 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cipromise_test(() => { 201cb0ef41Sopenharmony_ci const ts = recordingTransformStream({}, undefined, { highWaterMark: 1 }); 211cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 221cb0ef41Sopenharmony_ci // This call to write() resolves asynchronously. 231cb0ef41Sopenharmony_ci writer.write('a'); 241cb0ef41Sopenharmony_ci // This call to write() waits for backpressure that is never relieved and never calls transform(). 251cb0ef41Sopenharmony_ci writer.write('b'); 261cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 271cb0ef41Sopenharmony_ci assert_array_equals(ts.events, ['transform', 'a'], 'transform should be called once'); 281cb0ef41Sopenharmony_ci }); 291cb0ef41Sopenharmony_ci}, 'backpressure only allows one transform() with a identity transform with a readable HWM of 1 and no reader'); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cipromise_test(() => { 321cb0ef41Sopenharmony_ci // Without a transform() implementation, recordingTransformStream() never enqueues anything. 331cb0ef41Sopenharmony_ci const ts = recordingTransformStream({ 341cb0ef41Sopenharmony_ci transform() { 351cb0ef41Sopenharmony_ci // Discard all chunks. As a result, the readable side is never full enough to exert backpressure and transform() 361cb0ef41Sopenharmony_ci // keeps being called. 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci }, undefined, { highWaterMark: 1 }); 391cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 401cb0ef41Sopenharmony_ci const writePromises = []; 411cb0ef41Sopenharmony_ci for (let i = 0; i < 4; ++i) { 421cb0ef41Sopenharmony_ci writePromises.push(writer.write(i)); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci return Promise.all(writePromises).then(() => { 451cb0ef41Sopenharmony_ci assert_array_equals(ts.events, ['transform', 0, 'transform', 1, 'transform', 2, 'transform', 3], 461cb0ef41Sopenharmony_ci 'all 4 events should be transformed'); 471cb0ef41Sopenharmony_ci }); 481cb0ef41Sopenharmony_ci}, 'transform() should keep being called as long as there is no backpressure'); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cipromise_test(() => { 511cb0ef41Sopenharmony_ci const ts = new TransformStream({}, undefined, { highWaterMark: 1 }); 521cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 531cb0ef41Sopenharmony_ci const reader = ts.readable.getReader(); 541cb0ef41Sopenharmony_ci const events = []; 551cb0ef41Sopenharmony_ci const writerPromises = [ 561cb0ef41Sopenharmony_ci writer.write('a').then(() => events.push('a')), 571cb0ef41Sopenharmony_ci writer.write('b').then(() => events.push('b')), 581cb0ef41Sopenharmony_ci writer.close().then(() => events.push('closed'))]; 591cb0ef41Sopenharmony_ci return delay(0).then(() => { 601cb0ef41Sopenharmony_ci assert_array_equals(events, ['a'], 'the first write should have resolved'); 611cb0ef41Sopenharmony_ci return reader.read(); 621cb0ef41Sopenharmony_ci }).then(({ value, done }) => { 631cb0ef41Sopenharmony_ci assert_false(done, 'done should not be true'); 641cb0ef41Sopenharmony_ci assert_equals('a', value, 'value should be "a"'); 651cb0ef41Sopenharmony_ci return delay(0); 661cb0ef41Sopenharmony_ci }).then(() => { 671cb0ef41Sopenharmony_ci assert_array_equals(events, ['a', 'b', 'closed'], 'both writes and close() should have resolved'); 681cb0ef41Sopenharmony_ci return reader.read(); 691cb0ef41Sopenharmony_ci }).then(({ value, done }) => { 701cb0ef41Sopenharmony_ci assert_false(done, 'done should still not be true'); 711cb0ef41Sopenharmony_ci assert_equals('b', value, 'value should be "b"'); 721cb0ef41Sopenharmony_ci return reader.read(); 731cb0ef41Sopenharmony_ci }).then(({ done }) => { 741cb0ef41Sopenharmony_ci assert_true(done, 'done should be true'); 751cb0ef41Sopenharmony_ci return writerPromises; 761cb0ef41Sopenharmony_ci }); 771cb0ef41Sopenharmony_ci}, 'writes should resolve as soon as transform completes'); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_cipromise_test(() => { 801cb0ef41Sopenharmony_ci const ts = new TransformStream(undefined, undefined, { highWaterMark: 0 }); 811cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 821cb0ef41Sopenharmony_ci const reader = ts.readable.getReader(); 831cb0ef41Sopenharmony_ci const readPromise = reader.read(); 841cb0ef41Sopenharmony_ci writer.write('a'); 851cb0ef41Sopenharmony_ci return readPromise.then(({ value, done }) => { 861cb0ef41Sopenharmony_ci assert_false(done, 'not done'); 871cb0ef41Sopenharmony_ci assert_equals(value, 'a', 'value should be "a"'); 881cb0ef41Sopenharmony_ci }); 891cb0ef41Sopenharmony_ci}, 'calling pull() before the first write() with backpressure should work'); 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_cipromise_test(() => { 921cb0ef41Sopenharmony_ci let reader; 931cb0ef41Sopenharmony_ci const ts = recordingTransformStream({ 941cb0ef41Sopenharmony_ci transform(chunk, controller) { 951cb0ef41Sopenharmony_ci controller.enqueue(chunk); 961cb0ef41Sopenharmony_ci return reader.read(); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci }, undefined, { highWaterMark: 1 }); 991cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1001cb0ef41Sopenharmony_ci reader = ts.readable.getReader(); 1011cb0ef41Sopenharmony_ci return writer.write('a'); 1021cb0ef41Sopenharmony_ci}, 'transform() should be able to read the chunk it just enqueued'); 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_cipromise_test(() => { 1051cb0ef41Sopenharmony_ci let resolveTransform; 1061cb0ef41Sopenharmony_ci const transformPromise = new Promise(resolve => { 1071cb0ef41Sopenharmony_ci resolveTransform = resolve; 1081cb0ef41Sopenharmony_ci }); 1091cb0ef41Sopenharmony_ci const ts = recordingTransformStream({ 1101cb0ef41Sopenharmony_ci transform() { 1111cb0ef41Sopenharmony_ci return transformPromise; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci }, undefined, new CountQueuingStrategy({ highWaterMark: Infinity })); 1141cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1151cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); 1161cb0ef41Sopenharmony_ci return delay(0).then(() => { 1171cb0ef41Sopenharmony_ci writer.write('a'); 1181cb0ef41Sopenharmony_ci assert_array_equals(ts.events, ['transform', 'a']); 1191cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 0, 'desiredSize should be 0'); 1201cb0ef41Sopenharmony_ci return flushAsyncEvents(); 1211cb0ef41Sopenharmony_ci }).then(() => { 1221cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 0, 'desiredSize should still be 0'); 1231cb0ef41Sopenharmony_ci resolveTransform(); 1241cb0ef41Sopenharmony_ci return delay(0); 1251cb0ef41Sopenharmony_ci }).then(() => { 1261cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); 1271cb0ef41Sopenharmony_ci }); 1281cb0ef41Sopenharmony_ci}, 'blocking transform() should cause backpressure'); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_cipromise_test(t => { 1311cb0ef41Sopenharmony_ci const ts = new TransformStream(); 1321cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1331cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject'); 1341cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled during start'); 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_cipromise_test(t => { 1371cb0ef41Sopenharmony_ci const ts = new TransformStream({}, undefined, { highWaterMark: 0 }); 1381cb0ef41Sopenharmony_ci return delay(0).then(() => { 1391cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1401cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject'); 1411cb0ef41Sopenharmony_ci }); 1421cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled with backpressure'); 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_cipromise_test(t => { 1451cb0ef41Sopenharmony_ci const ts = new TransformStream({}, undefined, { highWaterMark: 1 }); 1461cb0ef41Sopenharmony_ci return delay(0).then(() => { 1471cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1481cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject'); 1491cb0ef41Sopenharmony_ci }); 1501cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled with no backpressure'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cipromise_test(() => { 1531cb0ef41Sopenharmony_ci const ts = new TransformStream({}, undefined, { highWaterMark: 1 }); 1541cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1551cb0ef41Sopenharmony_ci return delay(0).then(() => { 1561cb0ef41Sopenharmony_ci const writePromise = writer.write('a'); 1571cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1581cb0ef41Sopenharmony_ci return writePromise; 1591cb0ef41Sopenharmony_ci }); 1601cb0ef41Sopenharmony_ci}, 'cancelling the readable should cause a pending write to resolve'); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_cipromise_test(t => { 1631cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1641cb0ef41Sopenharmony_ci const ts = new TransformStream(); 1651cb0ef41Sopenharmony_ci const pipePromise = rs.pipeTo(ts.writable); 1661cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1671cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected'); 1681cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort an empty pipe'); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_cipromise_test(t => { 1711cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1721cb0ef41Sopenharmony_ci const ts = new TransformStream(); 1731cb0ef41Sopenharmony_ci const pipePromise = rs.pipeTo(ts.writable); 1741cb0ef41Sopenharmony_ci return delay(0).then(() => { 1751cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1761cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected'); 1771cb0ef41Sopenharmony_ci }); 1781cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort an empty pipe after startup'); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_cipromise_test(t => { 1811cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1821cb0ef41Sopenharmony_ci start(controller) { 1831cb0ef41Sopenharmony_ci controller.enqueue('a'); 1841cb0ef41Sopenharmony_ci controller.enqueue('b'); 1851cb0ef41Sopenharmony_ci controller.enqueue('c'); 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci }); 1881cb0ef41Sopenharmony_ci const ts = new TransformStream(); 1891cb0ef41Sopenharmony_ci const pipePromise = rs.pipeTo(ts.writable); 1901cb0ef41Sopenharmony_ci // Allow data to flow into the pipe. 1911cb0ef41Sopenharmony_ci return delay(0).then(() => { 1921cb0ef41Sopenharmony_ci ts.readable.cancel(error1); 1931cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected'); 1941cb0ef41Sopenharmony_ci }); 1951cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort a full pipe'); 196