11cb0ef41Sopenharmony_ci// META: global=window,worker 21cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js 31cb0ef41Sopenharmony_ci// META: script=../resources/rs-utils.js 41cb0ef41Sopenharmony_ci'use strict'; 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_citest(() => { 71cb0ef41Sopenharmony_ci new TransformStream({ transform() { } }); 81cb0ef41Sopenharmony_ci}, 'TransformStream can be constructed with a transform function'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_citest(() => { 111cb0ef41Sopenharmony_ci new TransformStream(); 121cb0ef41Sopenharmony_ci new TransformStream({}); 131cb0ef41Sopenharmony_ci}, 'TransformStream can be constructed with no transform function'); 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_citest(() => { 161cb0ef41Sopenharmony_ci const ts = new TransformStream({ transform() { } }); 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 191cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 1, 'writer.desiredSize should be 1'); 201cb0ef41Sopenharmony_ci}, 'TransformStream writable starts in the writable state'); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cipromise_test(() => { 231cb0ef41Sopenharmony_ci const ts = new TransformStream(); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 261cb0ef41Sopenharmony_ci writer.write('a'); 271cb0ef41Sopenharmony_ci assert_equals(writer.desiredSize, 0, 'writer.desiredSize should be 0 after write()'); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci return ts.readable.getReader().read().then(result => { 301cb0ef41Sopenharmony_ci assert_equals(result.value, 'a', 311cb0ef41Sopenharmony_ci 'result from reading the readable is the same as was written to writable'); 321cb0ef41Sopenharmony_ci assert_false(result.done, 'stream should not be done'); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci return delay(0).then(() => assert_equals(writer.desiredSize, 1, 'desiredSize should be 1 again')); 351cb0ef41Sopenharmony_ci }); 361cb0ef41Sopenharmony_ci}, 'Identity TransformStream: can read from readable what is put into writable'); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cipromise_test(() => { 391cb0ef41Sopenharmony_ci let c; 401cb0ef41Sopenharmony_ci const ts = new TransformStream({ 411cb0ef41Sopenharmony_ci start(controller) { 421cb0ef41Sopenharmony_ci c = controller; 431cb0ef41Sopenharmony_ci }, 441cb0ef41Sopenharmony_ci transform(chunk) { 451cb0ef41Sopenharmony_ci c.enqueue(chunk.toUpperCase()); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci }); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 501cb0ef41Sopenharmony_ci writer.write('a'); 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci return ts.readable.getReader().read().then(result => { 531cb0ef41Sopenharmony_ci assert_equals(result.value, 'A', 541cb0ef41Sopenharmony_ci 'result from reading the readable is the transformation of what was written to writable'); 551cb0ef41Sopenharmony_ci assert_false(result.done, 'stream should not be done'); 561cb0ef41Sopenharmony_ci }); 571cb0ef41Sopenharmony_ci}, 'Uppercaser sync TransformStream: can read from readable transformed version of what is put into writable'); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_cipromise_test(() => { 601cb0ef41Sopenharmony_ci let c; 611cb0ef41Sopenharmony_ci const ts = new TransformStream({ 621cb0ef41Sopenharmony_ci start(controller) { 631cb0ef41Sopenharmony_ci c = controller; 641cb0ef41Sopenharmony_ci }, 651cb0ef41Sopenharmony_ci transform(chunk) { 661cb0ef41Sopenharmony_ci c.enqueue(chunk.toUpperCase()); 671cb0ef41Sopenharmony_ci c.enqueue(chunk.toUpperCase()); 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci }); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 721cb0ef41Sopenharmony_ci writer.write('a'); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci const reader = ts.readable.getReader(); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci return reader.read().then(result1 => { 771cb0ef41Sopenharmony_ci assert_equals(result1.value, 'A', 781cb0ef41Sopenharmony_ci 'the first chunk read is the transformation of the single chunk written'); 791cb0ef41Sopenharmony_ci assert_false(result1.done, 'stream should not be done'); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci return reader.read().then(result2 => { 821cb0ef41Sopenharmony_ci assert_equals(result2.value, 'A', 831cb0ef41Sopenharmony_ci 'the second chunk read is also the transformation of the single chunk written'); 841cb0ef41Sopenharmony_ci assert_false(result2.done, 'stream should not be done'); 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci }); 871cb0ef41Sopenharmony_ci}, 'Uppercaser-doubler sync TransformStream: can read both chunks put into the readable'); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_cipromise_test(() => { 901cb0ef41Sopenharmony_ci let c; 911cb0ef41Sopenharmony_ci const ts = new TransformStream({ 921cb0ef41Sopenharmony_ci start(controller) { 931cb0ef41Sopenharmony_ci c = controller; 941cb0ef41Sopenharmony_ci }, 951cb0ef41Sopenharmony_ci transform(chunk) { 961cb0ef41Sopenharmony_ci return delay(0).then(() => c.enqueue(chunk.toUpperCase())); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci }); 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1011cb0ef41Sopenharmony_ci writer.write('a'); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci return ts.readable.getReader().read().then(result => { 1041cb0ef41Sopenharmony_ci assert_equals(result.value, 'A', 1051cb0ef41Sopenharmony_ci 'result from reading the readable is the transformation of what was written to writable'); 1061cb0ef41Sopenharmony_ci assert_false(result.done, 'stream should not be done'); 1071cb0ef41Sopenharmony_ci }); 1081cb0ef41Sopenharmony_ci}, 'Uppercaser async TransformStream: can read from readable transformed version of what is put into writable'); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_cipromise_test(() => { 1111cb0ef41Sopenharmony_ci let doSecondEnqueue; 1121cb0ef41Sopenharmony_ci let returnFromTransform; 1131cb0ef41Sopenharmony_ci const ts = new TransformStream({ 1141cb0ef41Sopenharmony_ci transform(chunk, controller) { 1151cb0ef41Sopenharmony_ci delay(0).then(() => controller.enqueue(chunk.toUpperCase())); 1161cb0ef41Sopenharmony_ci doSecondEnqueue = () => controller.enqueue(chunk.toUpperCase()); 1171cb0ef41Sopenharmony_ci return new Promise(resolve => { 1181cb0ef41Sopenharmony_ci returnFromTransform = resolve; 1191cb0ef41Sopenharmony_ci }); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci }); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci const reader = ts.readable.getReader(); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1261cb0ef41Sopenharmony_ci writer.write('a'); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci return reader.read().then(result1 => { 1291cb0ef41Sopenharmony_ci assert_equals(result1.value, 'A', 1301cb0ef41Sopenharmony_ci 'the first chunk read is the transformation of the single chunk written'); 1311cb0ef41Sopenharmony_ci assert_false(result1.done, 'stream should not be done'); 1321cb0ef41Sopenharmony_ci doSecondEnqueue(); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci return reader.read().then(result2 => { 1351cb0ef41Sopenharmony_ci assert_equals(result2.value, 'A', 1361cb0ef41Sopenharmony_ci 'the second chunk read is also the transformation of the single chunk written'); 1371cb0ef41Sopenharmony_ci assert_false(result2.done, 'stream should not be done'); 1381cb0ef41Sopenharmony_ci returnFromTransform(); 1391cb0ef41Sopenharmony_ci }); 1401cb0ef41Sopenharmony_ci }); 1411cb0ef41Sopenharmony_ci}, 'Uppercaser-doubler async TransformStream: can read both chunks put into the readable'); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_cipromise_test(() => { 1441cb0ef41Sopenharmony_ci const ts = new TransformStream({ transform() { } }); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1471cb0ef41Sopenharmony_ci writer.close(); 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci return Promise.all([writer.closed, ts.readable.getReader().closed]); 1501cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable (when there are no queued writes)'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cipromise_test(() => { 1531cb0ef41Sopenharmony_ci let transformResolve; 1541cb0ef41Sopenharmony_ci const transformPromise = new Promise(resolve => { 1551cb0ef41Sopenharmony_ci transformResolve = resolve; 1561cb0ef41Sopenharmony_ci }); 1571cb0ef41Sopenharmony_ci const ts = new TransformStream({ 1581cb0ef41Sopenharmony_ci transform() { 1591cb0ef41Sopenharmony_ci return transformPromise; 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci }, undefined, { highWaterMark: 1 }); 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1641cb0ef41Sopenharmony_ci writer.write('a'); 1651cb0ef41Sopenharmony_ci writer.close(); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci let rsClosed = false; 1681cb0ef41Sopenharmony_ci ts.readable.getReader().closed.then(() => { 1691cb0ef41Sopenharmony_ci rsClosed = true; 1701cb0ef41Sopenharmony_ci }); 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci return delay(0).then(() => { 1731cb0ef41Sopenharmony_ci assert_equals(rsClosed, false, 'readable is not closed after a tick'); 1741cb0ef41Sopenharmony_ci transformResolve(); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci return writer.closed.then(() => { 1771cb0ef41Sopenharmony_ci // TODO: Is this expectation correct? 1781cb0ef41Sopenharmony_ci assert_equals(rsClosed, true, 'readable is closed at that point'); 1791cb0ef41Sopenharmony_ci }); 1801cb0ef41Sopenharmony_ci }); 1811cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable waits for transforms to finish before closing both'); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_cipromise_test(() => { 1841cb0ef41Sopenharmony_ci let c; 1851cb0ef41Sopenharmony_ci const ts = new TransformStream({ 1861cb0ef41Sopenharmony_ci start(controller) { 1871cb0ef41Sopenharmony_ci c = controller; 1881cb0ef41Sopenharmony_ci }, 1891cb0ef41Sopenharmony_ci transform() { 1901cb0ef41Sopenharmony_ci c.enqueue('x'); 1911cb0ef41Sopenharmony_ci c.enqueue('y'); 1921cb0ef41Sopenharmony_ci return delay(0); 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci }); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 1971cb0ef41Sopenharmony_ci writer.write('a'); 1981cb0ef41Sopenharmony_ci writer.close(); 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci const readableChunks = readableStreamToArray(ts.readable); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci return writer.closed.then(() => { 2031cb0ef41Sopenharmony_ci return readableChunks.then(chunks => { 2041cb0ef41Sopenharmony_ci assert_array_equals(chunks, ['x', 'y'], 'both enqueued chunks can be read from the readable'); 2051cb0ef41Sopenharmony_ci }); 2061cb0ef41Sopenharmony_ci }); 2071cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable after sync enqueues and async done'); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_cipromise_test(() => { 2101cb0ef41Sopenharmony_ci let c; 2111cb0ef41Sopenharmony_ci const ts = new TransformStream({ 2121cb0ef41Sopenharmony_ci start(controller) { 2131cb0ef41Sopenharmony_ci c = controller; 2141cb0ef41Sopenharmony_ci }, 2151cb0ef41Sopenharmony_ci transform() { 2161cb0ef41Sopenharmony_ci return delay(0) 2171cb0ef41Sopenharmony_ci .then(() => c.enqueue('x')) 2181cb0ef41Sopenharmony_ci .then(() => c.enqueue('y')) 2191cb0ef41Sopenharmony_ci .then(() => delay(0)); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci }); 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 2241cb0ef41Sopenharmony_ci writer.write('a'); 2251cb0ef41Sopenharmony_ci writer.close(); 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci const readableChunks = readableStreamToArray(ts.readable); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci return writer.closed.then(() => { 2301cb0ef41Sopenharmony_ci return readableChunks.then(chunks => { 2311cb0ef41Sopenharmony_ci assert_array_equals(chunks, ['x', 'y'], 'both enqueued chunks can be read from the readable'); 2321cb0ef41Sopenharmony_ci }); 2331cb0ef41Sopenharmony_ci }); 2341cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable after async enqueues and async done'); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_cipromise_test(() => { 2371cb0ef41Sopenharmony_ci let c; 2381cb0ef41Sopenharmony_ci const ts = new TransformStream({ 2391cb0ef41Sopenharmony_ci suffix: '-suffix', 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci start(controller) { 2421cb0ef41Sopenharmony_ci c = controller; 2431cb0ef41Sopenharmony_ci c.enqueue('start' + this.suffix); 2441cb0ef41Sopenharmony_ci }, 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci transform(chunk) { 2471cb0ef41Sopenharmony_ci c.enqueue(chunk + this.suffix); 2481cb0ef41Sopenharmony_ci }, 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci flush() { 2511cb0ef41Sopenharmony_ci c.enqueue('flushed' + this.suffix); 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci }); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 2561cb0ef41Sopenharmony_ci writer.write('a'); 2571cb0ef41Sopenharmony_ci writer.close(); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci const readableChunks = readableStreamToArray(ts.readable); 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci return writer.closed.then(() => { 2621cb0ef41Sopenharmony_ci return readableChunks.then(chunks => { 2631cb0ef41Sopenharmony_ci assert_array_equals(chunks, ['start-suffix', 'a-suffix', 'flushed-suffix'], 'all enqueued chunks have suffixes'); 2641cb0ef41Sopenharmony_ci }); 2651cb0ef41Sopenharmony_ci }); 2661cb0ef41Sopenharmony_ci}, 'Transform stream should call transformer methods as methods'); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_cipromise_test(() => { 2691cb0ef41Sopenharmony_ci function functionWithOverloads() {} 2701cb0ef41Sopenharmony_ci functionWithOverloads.apply = () => assert_unreached('apply() should not be called'); 2711cb0ef41Sopenharmony_ci functionWithOverloads.call = () => assert_unreached('call() should not be called'); 2721cb0ef41Sopenharmony_ci const ts = new TransformStream({ 2731cb0ef41Sopenharmony_ci start: functionWithOverloads, 2741cb0ef41Sopenharmony_ci transform: functionWithOverloads, 2751cb0ef41Sopenharmony_ci flush: functionWithOverloads 2761cb0ef41Sopenharmony_ci }); 2771cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 2781cb0ef41Sopenharmony_ci writer.write('a'); 2791cb0ef41Sopenharmony_ci writer.close(); 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci return readableStreamToArray(ts.readable); 2821cb0ef41Sopenharmony_ci}, 'methods should not not have .apply() or .call() called'); 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_cipromise_test(t => { 2851cb0ef41Sopenharmony_ci let startCalled = false; 2861cb0ef41Sopenharmony_ci let startDone = false; 2871cb0ef41Sopenharmony_ci let transformDone = false; 2881cb0ef41Sopenharmony_ci let flushDone = false; 2891cb0ef41Sopenharmony_ci const ts = new TransformStream({ 2901cb0ef41Sopenharmony_ci start() { 2911cb0ef41Sopenharmony_ci startCalled = true; 2921cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 2931cb0ef41Sopenharmony_ci startDone = true; 2941cb0ef41Sopenharmony_ci }); 2951cb0ef41Sopenharmony_ci }, 2961cb0ef41Sopenharmony_ci transform() { 2971cb0ef41Sopenharmony_ci return t.step(() => { 2981cb0ef41Sopenharmony_ci assert_true(startDone, 'transform() should not be called until the promise returned from start() has resolved'); 2991cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 3001cb0ef41Sopenharmony_ci transformDone = true; 3011cb0ef41Sopenharmony_ci }); 3021cb0ef41Sopenharmony_ci }); 3031cb0ef41Sopenharmony_ci }, 3041cb0ef41Sopenharmony_ci flush() { 3051cb0ef41Sopenharmony_ci return t.step(() => { 3061cb0ef41Sopenharmony_ci assert_true(transformDone, 3071cb0ef41Sopenharmony_ci 'flush() should not be called until the promise returned from transform() has resolved'); 3081cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 3091cb0ef41Sopenharmony_ci flushDone = true; 3101cb0ef41Sopenharmony_ci }); 3111cb0ef41Sopenharmony_ci }); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci }, undefined, { highWaterMark: 1 }); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci assert_true(startCalled, 'start() should be called synchronously'); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 3181cb0ef41Sopenharmony_ci const writePromise = writer.write('a'); 3191cb0ef41Sopenharmony_ci return writer.close().then(() => { 3201cb0ef41Sopenharmony_ci assert_true(flushDone, 'promise returned from flush() should have resolved'); 3211cb0ef41Sopenharmony_ci return writePromise; 3221cb0ef41Sopenharmony_ci }); 3231cb0ef41Sopenharmony_ci}, 'TransformStream start, transform, and flush should be strictly ordered'); 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_cipromise_test(() => { 3261cb0ef41Sopenharmony_ci let transformCalled = false; 3271cb0ef41Sopenharmony_ci const ts = new TransformStream({ 3281cb0ef41Sopenharmony_ci transform() { 3291cb0ef41Sopenharmony_ci transformCalled = true; 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci }, undefined, { highWaterMark: Infinity }); 3321cb0ef41Sopenharmony_ci // transform() is only called synchronously when there is no backpressure and all microtasks have run. 3331cb0ef41Sopenharmony_ci return delay(0).then(() => { 3341cb0ef41Sopenharmony_ci const writePromise = ts.writable.getWriter().write(); 3351cb0ef41Sopenharmony_ci assert_true(transformCalled, 'transform() should have been called'); 3361cb0ef41Sopenharmony_ci return writePromise; 3371cb0ef41Sopenharmony_ci }); 3381cb0ef41Sopenharmony_ci}, 'it should be possible to call transform() synchronously'); 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_cipromise_test(() => { 3411cb0ef41Sopenharmony_ci const ts = new TransformStream({}, undefined, { highWaterMark: 0 }); 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci const writer = ts.writable.getWriter(); 3441cb0ef41Sopenharmony_ci writer.close(); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci return Promise.all([writer.closed, ts.readable.getReader().closed]); 3471cb0ef41Sopenharmony_ci}, 'closing the writable should close the readable when there are no queued chunks, even with backpressure'); 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_citest(() => { 3501cb0ef41Sopenharmony_ci new TransformStream({ 3511cb0ef41Sopenharmony_ci start(controller) { 3521cb0ef41Sopenharmony_ci controller.terminate(); 3531cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => controller.enqueue(), 'enqueue should throw'); 3541cb0ef41Sopenharmony_ci } 3551cb0ef41Sopenharmony_ci }); 3561cb0ef41Sopenharmony_ci}, 'enqueue() should throw after controller.terminate()'); 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_cipromise_test(() => { 3591cb0ef41Sopenharmony_ci let controller; 3601cb0ef41Sopenharmony_ci const ts = new TransformStream({ 3611cb0ef41Sopenharmony_ci start(c) { 3621cb0ef41Sopenharmony_ci controller = c; 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci }); 3651cb0ef41Sopenharmony_ci const cancelPromise = ts.readable.cancel(); 3661cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => controller.enqueue(), 'enqueue should throw'); 3671cb0ef41Sopenharmony_ci return cancelPromise; 3681cb0ef41Sopenharmony_ci}, 'enqueue() should throw after readable.cancel()'); 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_citest(() => { 3711cb0ef41Sopenharmony_ci new TransformStream({ 3721cb0ef41Sopenharmony_ci start(controller) { 3731cb0ef41Sopenharmony_ci controller.terminate(); 3741cb0ef41Sopenharmony_ci controller.terminate(); 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci }); 3771cb0ef41Sopenharmony_ci}, 'controller.terminate() should do nothing the second time it is called'); 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_cipromise_test(t => { 3801cb0ef41Sopenharmony_ci let controller; 3811cb0ef41Sopenharmony_ci const ts = new TransformStream({ 3821cb0ef41Sopenharmony_ci start(c) { 3831cb0ef41Sopenharmony_ci controller = c; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci }); 3861cb0ef41Sopenharmony_ci const cancelReason = { name: 'cancelReason' }; 3871cb0ef41Sopenharmony_ci const cancelPromise = ts.readable.cancel(cancelReason); 3881cb0ef41Sopenharmony_ci controller.terminate(); 3891cb0ef41Sopenharmony_ci return Promise.all([ 3901cb0ef41Sopenharmony_ci cancelPromise, 3911cb0ef41Sopenharmony_ci promise_rejects_exactly(t, cancelReason, ts.writable.getWriter().closed, 'closed should reject with cancelReason') 3921cb0ef41Sopenharmony_ci ]); 3931cb0ef41Sopenharmony_ci}, 'terminate() should do nothing after readable.cancel()'); 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_cipromise_test(() => { 3961cb0ef41Sopenharmony_ci let calls = 0; 3971cb0ef41Sopenharmony_ci new TransformStream({ 3981cb0ef41Sopenharmony_ci start() { 3991cb0ef41Sopenharmony_ci ++calls; 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci }); 4021cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 4031cb0ef41Sopenharmony_ci assert_equals(calls, 1, 'start() should have been called exactly once'); 4041cb0ef41Sopenharmony_ci }); 4051cb0ef41Sopenharmony_ci}, 'start() should not be called twice'); 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_citest(() => { 4081cb0ef41Sopenharmony_ci assert_throws_js(RangeError, () => new TransformStream({ readableType: 'bytes' }), 'constructor should throw'); 4091cb0ef41Sopenharmony_ci}, 'specifying a defined readableType should throw'); 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_citest(() => { 4121cb0ef41Sopenharmony_ci assert_throws_js(RangeError, () => new TransformStream({ writableType: 'bytes' }), 'constructor should throw'); 4131cb0ef41Sopenharmony_ci}, 'specifying a defined writableType should throw'); 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_citest(() => { 4161cb0ef41Sopenharmony_ci class Subclass extends TransformStream { 4171cb0ef41Sopenharmony_ci extraFunction() { 4181cb0ef41Sopenharmony_ci return true; 4191cb0ef41Sopenharmony_ci } 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci assert_equals( 4221cb0ef41Sopenharmony_ci Object.getPrototypeOf(Subclass.prototype), TransformStream.prototype, 4231cb0ef41Sopenharmony_ci 'Subclass.prototype\'s prototype should be TransformStream.prototype'); 4241cb0ef41Sopenharmony_ci assert_equals(Object.getPrototypeOf(Subclass), TransformStream, 4251cb0ef41Sopenharmony_ci 'Subclass\'s prototype should be TransformStream'); 4261cb0ef41Sopenharmony_ci const sub = new Subclass(); 4271cb0ef41Sopenharmony_ci assert_true(sub instanceof TransformStream, 4281cb0ef41Sopenharmony_ci 'Subclass object should be an instance of TransformStream'); 4291cb0ef41Sopenharmony_ci assert_true(sub instanceof Subclass, 4301cb0ef41Sopenharmony_ci 'Subclass object should be an instance of Subclass'); 4311cb0ef41Sopenharmony_ci const readableGetter = Object.getOwnPropertyDescriptor( 4321cb0ef41Sopenharmony_ci TransformStream.prototype, 'readable').get; 4331cb0ef41Sopenharmony_ci assert_equals(readableGetter.call(sub), sub.readable, 4341cb0ef41Sopenharmony_ci 'Subclass object should pass brand check'); 4351cb0ef41Sopenharmony_ci assert_true(sub.extraFunction(), 4361cb0ef41Sopenharmony_ci 'extraFunction() should be present on Subclass object'); 4371cb0ef41Sopenharmony_ci}, 'Subclassing TransformStream should work'); 438