11cb0ef41Sopenharmony_ci// META: global=window,worker 21cb0ef41Sopenharmony_ci// META: script=../resources/rs-utils.js 31cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js 41cb0ef41Sopenharmony_ci// META: script=../resources/recording-streams.js 51cb0ef41Sopenharmony_ci'use strict'; 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cifunction duckTypedPassThroughTransform() { 81cb0ef41Sopenharmony_ci let enqueueInReadable; 91cb0ef41Sopenharmony_ci let closeReadable; 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci return { 121cb0ef41Sopenharmony_ci writable: new WritableStream({ 131cb0ef41Sopenharmony_ci write(chunk) { 141cb0ef41Sopenharmony_ci enqueueInReadable(chunk); 151cb0ef41Sopenharmony_ci }, 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci close() { 181cb0ef41Sopenharmony_ci closeReadable(); 191cb0ef41Sopenharmony_ci } 201cb0ef41Sopenharmony_ci }), 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci readable: new ReadableStream({ 231cb0ef41Sopenharmony_ci start(c) { 241cb0ef41Sopenharmony_ci enqueueInReadable = c.enqueue.bind(c); 251cb0ef41Sopenharmony_ci closeReadable = c.close.bind(c); 261cb0ef41Sopenharmony_ci } 271cb0ef41Sopenharmony_ci }) 281cb0ef41Sopenharmony_ci }; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cifunction uninterestingReadableWritablePair() { 321cb0ef41Sopenharmony_ci return { writable: new WritableStream(), readable: new ReadableStream() }; 331cb0ef41Sopenharmony_ci} 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cipromise_test(() => { 361cb0ef41Sopenharmony_ci const readableEnd = sequentialReadableStream(5).pipeThrough(duckTypedPassThroughTransform()); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci return readableStreamToArray(readableEnd).then(chunks => 391cb0ef41Sopenharmony_ci assert_array_equals(chunks, [1, 2, 3, 4, 5]), 'chunks should match'); 401cb0ef41Sopenharmony_ci}, 'Piping through a duck-typed pass-through transform stream should work'); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cipromise_test(() => { 431cb0ef41Sopenharmony_ci const transform = { 441cb0ef41Sopenharmony_ci writable: new WritableStream({ 451cb0ef41Sopenharmony_ci start(c) { 461cb0ef41Sopenharmony_ci c.error(new Error('this rejection should not be reported as unhandled')); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci }), 491cb0ef41Sopenharmony_ci readable: new ReadableStream() 501cb0ef41Sopenharmony_ci }; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci sequentialReadableStream(5).pipeThrough(transform); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // The test harness should complain about unhandled rejections by then. 551cb0ef41Sopenharmony_ci return flushAsyncEvents(); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci}, 'Piping through a transform errored on the writable end does not cause an unhandled promise rejection'); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_citest(() => { 601cb0ef41Sopenharmony_ci let calledPipeTo = false; 611cb0ef41Sopenharmony_ci class BadReadableStream extends ReadableStream { 621cb0ef41Sopenharmony_ci pipeTo() { 631cb0ef41Sopenharmony_ci calledPipeTo = true; 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci const brs = new BadReadableStream({ 681cb0ef41Sopenharmony_ci start(controller) { 691cb0ef41Sopenharmony_ci controller.close(); 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci }); 721cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 731cb0ef41Sopenharmony_ci const writable = new WritableStream(); 741cb0ef41Sopenharmony_ci const result = brs.pipeThrough({ readable, writable }); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci assert_false(calledPipeTo, 'the overridden pipeTo should not have been called'); 771cb0ef41Sopenharmony_ci assert_equals(result, readable, 'return value should be the passed readable property'); 781cb0ef41Sopenharmony_ci}, 'pipeThrough should not call pipeTo on this'); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_citest(t => { 811cb0ef41Sopenharmony_ci let calledFakePipeTo = false; 821cb0ef41Sopenharmony_ci const realPipeTo = ReadableStream.prototype.pipeTo; 831cb0ef41Sopenharmony_ci t.add_cleanup(() => { 841cb0ef41Sopenharmony_ci ReadableStream.prototype.pipeTo = realPipeTo; 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci ReadableStream.prototype.pipeTo = () => { 871cb0ef41Sopenharmony_ci calledFakePipeTo = true; 881cb0ef41Sopenharmony_ci }; 891cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 901cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 911cb0ef41Sopenharmony_ci const writable = new WritableStream(); 921cb0ef41Sopenharmony_ci const result = rs.pipeThrough({ readable, writable }); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci assert_false(calledFakePipeTo, 'the monkey-patched pipeTo should not have been called'); 951cb0ef41Sopenharmony_ci assert_equals(result, readable, 'return value should be the passed readable property'); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci}, 'pipeThrough should not call pipeTo on the ReadableStream prototype'); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ciconst badReadables = [null, undefined, 0, NaN, true, 'ReadableStream', Object.create(ReadableStream.prototype)]; 1001cb0ef41Sopenharmony_cifor (const readable of badReadables) { 1011cb0ef41Sopenharmony_ci test(() => { 1021cb0ef41Sopenharmony_ci assert_throws_js(TypeError, 1031cb0ef41Sopenharmony_ci ReadableStream.prototype.pipeThrough.bind(readable, uninterestingReadableWritablePair()), 1041cb0ef41Sopenharmony_ci 'pipeThrough should throw'); 1051cb0ef41Sopenharmony_ci }, `pipeThrough should brand-check this and not allow '${readable}'`); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci test(() => { 1081cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1091cb0ef41Sopenharmony_ci let writableGetterCalled = false; 1101cb0ef41Sopenharmony_ci assert_throws_js( 1111cb0ef41Sopenharmony_ci TypeError, 1121cb0ef41Sopenharmony_ci () => rs.pipeThrough({ 1131cb0ef41Sopenharmony_ci get writable() { 1141cb0ef41Sopenharmony_ci writableGetterCalled = true; 1151cb0ef41Sopenharmony_ci return new WritableStream(); 1161cb0ef41Sopenharmony_ci }, 1171cb0ef41Sopenharmony_ci readable 1181cb0ef41Sopenharmony_ci }), 1191cb0ef41Sopenharmony_ci 'pipeThrough should brand-check readable' 1201cb0ef41Sopenharmony_ci ); 1211cb0ef41Sopenharmony_ci assert_false(writableGetterCalled, 'writable should not have been accessed'); 1221cb0ef41Sopenharmony_ci }, `pipeThrough should brand-check readable and not allow '${readable}'`); 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ciconst badWritables = [null, undefined, 0, NaN, true, 'WritableStream', Object.create(WritableStream.prototype)]; 1261cb0ef41Sopenharmony_cifor (const writable of badWritables) { 1271cb0ef41Sopenharmony_ci test(() => { 1281cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1291cb0ef41Sopenharmony_ci start(c) { 1301cb0ef41Sopenharmony_ci c.close(); 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci }); 1331cb0ef41Sopenharmony_ci let readableGetterCalled = false; 1341cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => rs.pipeThrough({ 1351cb0ef41Sopenharmony_ci get readable() { 1361cb0ef41Sopenharmony_ci readableGetterCalled = true; 1371cb0ef41Sopenharmony_ci return new ReadableStream(); 1381cb0ef41Sopenharmony_ci }, 1391cb0ef41Sopenharmony_ci writable 1401cb0ef41Sopenharmony_ci }), 1411cb0ef41Sopenharmony_ci 'pipeThrough should brand-check writable'); 1421cb0ef41Sopenharmony_ci assert_true(readableGetterCalled, 'readable should have been accessed'); 1431cb0ef41Sopenharmony_ci }, `pipeThrough should brand-check writable and not allow '${writable}'`); 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_citest(t => { 1471cb0ef41Sopenharmony_ci const error = new Error(); 1481cb0ef41Sopenharmony_ci error.name = 'custom'; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1511cb0ef41Sopenharmony_ci pull: t.unreached_func('pull should not be called') 1521cb0ef41Sopenharmony_ci }, { highWaterMark: 0 }); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci const throwingWritable = { 1551cb0ef41Sopenharmony_ci readable: rs, 1561cb0ef41Sopenharmony_ci get writable() { 1571cb0ef41Sopenharmony_ci throw error; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci }; 1601cb0ef41Sopenharmony_ci assert_throws_exactly(error, 1611cb0ef41Sopenharmony_ci () => ReadableStream.prototype.pipeThrough.call(rs, throwingWritable, {}), 1621cb0ef41Sopenharmony_ci 'pipeThrough should rethrow the error thrown by the writable getter'); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci const throwingReadable = { 1651cb0ef41Sopenharmony_ci get readable() { 1661cb0ef41Sopenharmony_ci throw error; 1671cb0ef41Sopenharmony_ci }, 1681cb0ef41Sopenharmony_ci writable: {} 1691cb0ef41Sopenharmony_ci }; 1701cb0ef41Sopenharmony_ci assert_throws_exactly(error, 1711cb0ef41Sopenharmony_ci () => ReadableStream.prototype.pipeThrough.call(rs, throwingReadable, {}), 1721cb0ef41Sopenharmony_ci 'pipeThrough should rethrow the error thrown by the readable getter'); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci}, 'pipeThrough should rethrow errors from accessing readable or writable'); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ciconst badSignals = [null, 0, NaN, true, 'AbortSignal', Object.create(AbortSignal.prototype)]; 1771cb0ef41Sopenharmony_cifor (const signal of badSignals) { 1781cb0ef41Sopenharmony_ci test(() => { 1791cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1801cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => rs.pipeThrough(uninterestingReadableWritablePair(), { signal }), 1811cb0ef41Sopenharmony_ci 'pipeThrough should throw'); 1821cb0ef41Sopenharmony_ci }, `invalid values of signal should throw; specifically '${signal}'`); 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_citest(() => { 1861cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1871cb0ef41Sopenharmony_ci const controller = new AbortController(); 1881cb0ef41Sopenharmony_ci const signal = controller.signal; 1891cb0ef41Sopenharmony_ci rs.pipeThrough(uninterestingReadableWritablePair(), { signal }); 1901cb0ef41Sopenharmony_ci}, 'pipeThrough should accept a real AbortSignal'); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_citest(() => { 1931cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 1941cb0ef41Sopenharmony_ci rs.getReader(); 1951cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => rs.pipeThrough(uninterestingReadableWritablePair()), 1961cb0ef41Sopenharmony_ci 'pipeThrough should throw'); 1971cb0ef41Sopenharmony_ci}, 'pipeThrough should throw if this is locked'); 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_citest(() => { 2001cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2011cb0ef41Sopenharmony_ci const writable = new WritableStream(); 2021cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2031cb0ef41Sopenharmony_ci writable.getWriter(); 2041cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => rs.pipeThrough({writable, readable}), 2051cb0ef41Sopenharmony_ci 'pipeThrough should throw'); 2061cb0ef41Sopenharmony_ci}, 'pipeThrough should throw if writable is locked'); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_citest(() => { 2091cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2101cb0ef41Sopenharmony_ci const writable = new WritableStream(); 2111cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2121cb0ef41Sopenharmony_ci readable.getReader(); 2131cb0ef41Sopenharmony_ci assert_equals(rs.pipeThrough({ writable, readable }), readable, 2141cb0ef41Sopenharmony_ci 'pipeThrough should not throw'); 2151cb0ef41Sopenharmony_ci}, 'pipeThrough should not care if readable is locked'); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_cipromise_test(() => { 2181cb0ef41Sopenharmony_ci const rs = recordingReadableStream(); 2191cb0ef41Sopenharmony_ci const writable = new WritableStream({ 2201cb0ef41Sopenharmony_ci start(controller) { 2211cb0ef41Sopenharmony_ci controller.error(); 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci }); 2241cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2251cb0ef41Sopenharmony_ci rs.pipeThrough({ writable, readable }, { preventCancel: true }); 2261cb0ef41Sopenharmony_ci return flushAsyncEvents(0).then(() => { 2271cb0ef41Sopenharmony_ci assert_array_equals(rs.events, ['pull'], 'cancel should not have been called'); 2281cb0ef41Sopenharmony_ci }); 2291cb0ef41Sopenharmony_ci}, 'preventCancel should work'); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_cipromise_test(() => { 2321cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 2331cb0ef41Sopenharmony_ci start(controller) { 2341cb0ef41Sopenharmony_ci controller.close(); 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci }); 2371cb0ef41Sopenharmony_ci const writable = recordingWritableStream(); 2381cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2391cb0ef41Sopenharmony_ci rs.pipeThrough({ writable, readable }, { preventClose: true }); 2401cb0ef41Sopenharmony_ci return flushAsyncEvents(0).then(() => { 2411cb0ef41Sopenharmony_ci assert_array_equals(writable.events, [], 'writable should not be closed'); 2421cb0ef41Sopenharmony_ci }); 2431cb0ef41Sopenharmony_ci}, 'preventClose should work'); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_cipromise_test(() => { 2461cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 2471cb0ef41Sopenharmony_ci start(controller) { 2481cb0ef41Sopenharmony_ci controller.error(); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci }); 2511cb0ef41Sopenharmony_ci const writable = recordingWritableStream(); 2521cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2531cb0ef41Sopenharmony_ci rs.pipeThrough({ writable, readable }, { preventAbort: true }); 2541cb0ef41Sopenharmony_ci return flushAsyncEvents(0).then(() => { 2551cb0ef41Sopenharmony_ci assert_array_equals(writable.events, [], 'writable should not be aborted'); 2561cb0ef41Sopenharmony_ci }); 2571cb0ef41Sopenharmony_ci}, 'preventAbort should work'); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_citest(() => { 2601cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2611cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2621cb0ef41Sopenharmony_ci const writable = new WritableStream(); 2631cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => rs.pipeThrough({readable, writable}, { 2641cb0ef41Sopenharmony_ci get preventAbort() { 2651cb0ef41Sopenharmony_ci writable.getWriter(); 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci }), 'pipeThrough should throw'); 2681cb0ef41Sopenharmony_ci}, 'pipeThrough() should throw if an option getter grabs a writer'); 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_citest(() => { 2711cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2721cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2731cb0ef41Sopenharmony_ci const writable = new WritableStream(); 2741cb0ef41Sopenharmony_ci rs.pipeThrough({readable, writable}, null); 2751cb0ef41Sopenharmony_ci}, 'pipeThrough() should not throw if option is null'); 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_citest(() => { 2781cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2791cb0ef41Sopenharmony_ci const readable = new ReadableStream(); 2801cb0ef41Sopenharmony_ci const writable = new WritableStream(); 2811cb0ef41Sopenharmony_ci rs.pipeThrough({readable, writable}, {signal:undefined}); 2821cb0ef41Sopenharmony_ci}, 'pipeThrough() should not throw if signal is undefined'); 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_cifunction tryPipeThrough(pair, options) 2851cb0ef41Sopenharmony_ci{ 2861cb0ef41Sopenharmony_ci const rs = new ReadableStream(); 2871cb0ef41Sopenharmony_ci if (!pair) 2881cb0ef41Sopenharmony_ci pair = {readable:new ReadableStream(), writable:new WritableStream()}; 2891cb0ef41Sopenharmony_ci try { 2901cb0ef41Sopenharmony_ci rs.pipeThrough(pair, options) 2911cb0ef41Sopenharmony_ci } catch (e) { 2921cb0ef41Sopenharmony_ci return e; 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci} 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_citest(() => { 2971cb0ef41Sopenharmony_ci let result = tryPipeThrough({ 2981cb0ef41Sopenharmony_ci get readable() { 2991cb0ef41Sopenharmony_ci return new ReadableStream(); 3001cb0ef41Sopenharmony_ci }, 3011cb0ef41Sopenharmony_ci get writable() { 3021cb0ef41Sopenharmony_ci throw "writable threw"; 3031cb0ef41Sopenharmony_ci } 3041cb0ef41Sopenharmony_ci }, { }); 3051cb0ef41Sopenharmony_ci assert_equals(result, "writable threw"); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci result = tryPipeThrough({ 3081cb0ef41Sopenharmony_ci get readable() { 3091cb0ef41Sopenharmony_ci throw "readable threw"; 3101cb0ef41Sopenharmony_ci }, 3111cb0ef41Sopenharmony_ci get writable() { 3121cb0ef41Sopenharmony_ci throw "writable threw"; 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci }, { }); 3151cb0ef41Sopenharmony_ci assert_equals(result, "readable threw"); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci result = tryPipeThrough({ 3181cb0ef41Sopenharmony_ci get readable() { 3191cb0ef41Sopenharmony_ci throw "readable threw"; 3201cb0ef41Sopenharmony_ci }, 3211cb0ef41Sopenharmony_ci get writable() { 3221cb0ef41Sopenharmony_ci throw "writable threw"; 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci }, { 3251cb0ef41Sopenharmony_ci get preventAbort() { 3261cb0ef41Sopenharmony_ci throw "preventAbort threw"; 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci }); 3291cb0ef41Sopenharmony_ci assert_equals(result, "readable threw"); 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci}, 'pipeThrough() should throw if readable/writable getters throw'); 332