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_ciconst error1 = new Error('error1'); 71cb0ef41Sopenharmony_cierror1.name = 'error1'; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_citest(() => { 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci new ReadableStream(); // ReadableStream constructed with no parameters 121cb0ef41Sopenharmony_ci new ReadableStream({ }); // ReadableStream constructed with an empty object as parameter 131cb0ef41Sopenharmony_ci new ReadableStream({ type: undefined }); // ReadableStream constructed with undefined type 141cb0ef41Sopenharmony_ci new ReadableStream(undefined); // ReadableStream constructed with undefined as parameter 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci let x; 171cb0ef41Sopenharmony_ci new ReadableStream(x); // ReadableStream constructed with an undefined variable as parameter 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci}, 'ReadableStream can be constructed with no errors'); 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_citest(() => { 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream(null), 'constructor should throw when the source is null'); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci}, 'ReadableStream can\'t be constructed with garbage'); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_citest(() => { 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream({ type: null }), 301cb0ef41Sopenharmony_ci 'constructor should throw when the type is null'); 311cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream({ type: '' }), 321cb0ef41Sopenharmony_ci 'constructor should throw when the type is empty string'); 331cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream({ type: 'asdf' }), 341cb0ef41Sopenharmony_ci 'constructor should throw when the type is asdf'); 351cb0ef41Sopenharmony_ci assert_throws_exactly( 361cb0ef41Sopenharmony_ci error1, 371cb0ef41Sopenharmony_ci () => new ReadableStream({ type: { get toString() { throw error1; } } }), 381cb0ef41Sopenharmony_ci 'constructor should throw when ToString() throws' 391cb0ef41Sopenharmony_ci ); 401cb0ef41Sopenharmony_ci assert_throws_exactly( 411cb0ef41Sopenharmony_ci error1, 421cb0ef41Sopenharmony_ci () => new ReadableStream({ type: { toString() { throw error1; } } }), 431cb0ef41Sopenharmony_ci 'constructor should throw when ToString() throws' 441cb0ef41Sopenharmony_ci ); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci}, 'ReadableStream can\'t be constructed with an invalid type'); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_citest(() => { 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => { 511cb0ef41Sopenharmony_ci new ReadableStream({ start: 'potato' }); 521cb0ef41Sopenharmony_ci }, 'constructor should throw when start is not a function'); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci}, 'ReadableStream constructor should throw for non-function start arguments'); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_citest(() => { 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream({ cancel: '2' }), 'constructor should throw'); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci}, 'ReadableStream constructor will not tolerate initial garbage as cancel argument'); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_citest(() => { 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => new ReadableStream({ pull: { } }), 'constructor should throw'); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci}, 'ReadableStream constructor will not tolerate initial garbage as pull argument'); 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_citest(() => { 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci let startCalled = false; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci const source = { 731cb0ef41Sopenharmony_ci start() { 741cb0ef41Sopenharmony_ci assert_equals(this, source, 'source is this during start'); 751cb0ef41Sopenharmony_ci startCalled = true; 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci }; 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci new ReadableStream(source); 801cb0ef41Sopenharmony_ci assert_true(startCalled); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci}, 'ReadableStream start should be called with the proper thisArg'); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_citest(() => { 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci let startCalled = false; 871cb0ef41Sopenharmony_ci const source = { 881cb0ef41Sopenharmony_ci start(controller) { 891cb0ef41Sopenharmony_ci const properties = ['close', 'constructor', 'desiredSize', 'enqueue', 'error']; 901cb0ef41Sopenharmony_ci assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties, 911cb0ef41Sopenharmony_ci 'prototype should have the right properties'); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci controller.test = ''; 941cb0ef41Sopenharmony_ci assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties, 951cb0ef41Sopenharmony_ci 'prototype should still have the right properties'); 961cb0ef41Sopenharmony_ci assert_not_equals(Object.getOwnPropertyNames(controller).indexOf('test'), -1, 971cb0ef41Sopenharmony_ci '"test" should be a property of the controller'); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci startCalled = true; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci }; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci new ReadableStream(source); 1041cb0ef41Sopenharmony_ci assert_true(startCalled); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci}, 'ReadableStream start controller parameter should be extensible'); 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_citest(() => { 1091cb0ef41Sopenharmony_ci (new ReadableStream()).getReader(undefined); 1101cb0ef41Sopenharmony_ci (new ReadableStream()).getReader({}); 1111cb0ef41Sopenharmony_ci (new ReadableStream()).getReader({ mode: undefined, notmode: 'ignored' }); 1121cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => (new ReadableStream()).getReader({ mode: 'potato' })); 1131cb0ef41Sopenharmony_ci}, 'default ReadableStream getReader() should only accept mode:undefined'); 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_cipromise_test(() => { 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci function SimpleStreamSource() {} 1181cb0ef41Sopenharmony_ci let resolve; 1191cb0ef41Sopenharmony_ci const promise = new Promise(r => resolve = r); 1201cb0ef41Sopenharmony_ci SimpleStreamSource.prototype = { 1211cb0ef41Sopenharmony_ci start: resolve 1221cb0ef41Sopenharmony_ci }; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci new ReadableStream(new SimpleStreamSource()); 1251cb0ef41Sopenharmony_ci return promise; 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci}, 'ReadableStream should be able to call start method within prototype chain of its source'); 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_cipromise_test(() => { 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1321cb0ef41Sopenharmony_ci start(c) { 1331cb0ef41Sopenharmony_ci return delay(5).then(() => { 1341cb0ef41Sopenharmony_ci c.enqueue('a'); 1351cb0ef41Sopenharmony_ci c.close(); 1361cb0ef41Sopenharmony_ci }); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci }); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci const reader = rs.getReader(); 1411cb0ef41Sopenharmony_ci return reader.read().then(r => { 1421cb0ef41Sopenharmony_ci assert_object_equals(r, { value: 'a', done: false }, 'value read should be the one enqueued'); 1431cb0ef41Sopenharmony_ci return reader.closed; 1441cb0ef41Sopenharmony_ci }); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci}, 'ReadableStream start should be able to return a promise'); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_cipromise_test(() => { 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci const theError = new Error('rejected!'); 1511cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1521cb0ef41Sopenharmony_ci start() { 1531cb0ef41Sopenharmony_ci return delay(1).then(() => { 1541cb0ef41Sopenharmony_ci throw theError; 1551cb0ef41Sopenharmony_ci }); 1561cb0ef41Sopenharmony_ci } 1571cb0ef41Sopenharmony_ci }); 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci return rs.getReader().closed.then(() => { 1601cb0ef41Sopenharmony_ci assert_unreached('closed promise should be rejected'); 1611cb0ef41Sopenharmony_ci }, e => { 1621cb0ef41Sopenharmony_ci assert_equals(e, theError, 'promise should be rejected with the same error'); 1631cb0ef41Sopenharmony_ci }); 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci}, 'ReadableStream start should be able to return a promise and reject it'); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_cipromise_test(() => { 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci const objects = [ 1701cb0ef41Sopenharmony_ci { potato: 'Give me more!' }, 1711cb0ef41Sopenharmony_ci 'test', 1721cb0ef41Sopenharmony_ci 1 1731cb0ef41Sopenharmony_ci ]; 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1761cb0ef41Sopenharmony_ci start(c) { 1771cb0ef41Sopenharmony_ci for (const o of objects) { 1781cb0ef41Sopenharmony_ci c.enqueue(o); 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci c.close(); 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci }); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci const reader = rs.getReader(); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci return Promise.all([reader.read(), reader.read(), reader.read(), reader.closed]).then(r => { 1871cb0ef41Sopenharmony_ci assert_object_equals(r[0], { value: objects[0], done: false }, 'value read should be the one enqueued'); 1881cb0ef41Sopenharmony_ci assert_object_equals(r[1], { value: objects[1], done: false }, 'value read should be the one enqueued'); 1891cb0ef41Sopenharmony_ci assert_object_equals(r[2], { value: objects[2], done: false }, 'value read should be the one enqueued'); 1901cb0ef41Sopenharmony_ci }); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci}, 'ReadableStream should be able to enqueue different objects.'); 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_cipromise_test(() => { 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci const error = new Error('pull failure'); 1971cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 1981cb0ef41Sopenharmony_ci pull() { 1991cb0ef41Sopenharmony_ci return Promise.reject(error); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci }); 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci const reader = rs.getReader(); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci let closed = false; 2061cb0ef41Sopenharmony_ci let read = false; 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci return Promise.all([ 2091cb0ef41Sopenharmony_ci reader.closed.then(() => { 2101cb0ef41Sopenharmony_ci assert_unreached('closed should be rejected'); 2111cb0ef41Sopenharmony_ci }, e => { 2121cb0ef41Sopenharmony_ci closed = true; 2131cb0ef41Sopenharmony_ci assert_false(read); 2141cb0ef41Sopenharmony_ci assert_equals(e, error, 'closed should be rejected with the thrown error'); 2151cb0ef41Sopenharmony_ci }), 2161cb0ef41Sopenharmony_ci reader.read().then(() => { 2171cb0ef41Sopenharmony_ci assert_unreached('read() should be rejected'); 2181cb0ef41Sopenharmony_ci }, e => { 2191cb0ef41Sopenharmony_ci read = true; 2201cb0ef41Sopenharmony_ci assert_true(closed); 2211cb0ef41Sopenharmony_ci assert_equals(e, error, 'read() should be rejected with the thrown error'); 2221cb0ef41Sopenharmony_ci }) 2231cb0ef41Sopenharmony_ci ]); 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci}, 'ReadableStream: if pull rejects, it should error the stream'); 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_cipromise_test(() => { 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci let pullCount = 0; 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci new ReadableStream({ 2321cb0ef41Sopenharmony_ci pull() { 2331cb0ef41Sopenharmony_ci pullCount++; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci }); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 2381cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called once start finishes'); 2391cb0ef41Sopenharmony_ci return delay(10); 2401cb0ef41Sopenharmony_ci }).then(() => { 2411cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called exactly once'); 2421cb0ef41Sopenharmony_ci }); 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once upon starting the stream'); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_cipromise_test(() => { 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci let pullCount = 0; 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 2511cb0ef41Sopenharmony_ci pull(c) { 2521cb0ef41Sopenharmony_ci // Don't enqueue immediately after start. We want the stream to be empty when we call .read() on it. 2531cb0ef41Sopenharmony_ci if (pullCount > 0) { 2541cb0ef41Sopenharmony_ci c.enqueue(pullCount); 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci ++pullCount; 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci }); 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 2611cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called once start finishes'); 2621cb0ef41Sopenharmony_ci }).then(() => { 2631cb0ef41Sopenharmony_ci const reader = rs.getReader(); 2641cb0ef41Sopenharmony_ci const read = reader.read(); 2651cb0ef41Sopenharmony_ci assert_equals(pullCount, 2, 'pull should be called when read is called'); 2661cb0ef41Sopenharmony_ci return read; 2671cb0ef41Sopenharmony_ci }).then(result => { 2681cb0ef41Sopenharmony_ci assert_equals(pullCount, 3, 'pull should be called again in reaction to calling read'); 2691cb0ef41Sopenharmony_ci assert_object_equals(result, { value: 1, done: false }, 'the result read should be the one enqueued'); 2701cb0ef41Sopenharmony_ci }); 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull when trying to read from a started, empty stream'); 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_cipromise_test(() => { 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci let pullCount = 0; 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 2791cb0ef41Sopenharmony_ci start(c) { 2801cb0ef41Sopenharmony_ci c.enqueue('a'); 2811cb0ef41Sopenharmony_ci }, 2821cb0ef41Sopenharmony_ci pull() { 2831cb0ef41Sopenharmony_ci pullCount++; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci }); 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci const read = rs.getReader().read(); 2881cb0ef41Sopenharmony_ci assert_equals(pullCount, 0, 'calling read() should not cause pull to be called yet'); 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 2911cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called once start finishes'); 2921cb0ef41Sopenharmony_ci return read; 2931cb0ef41Sopenharmony_ci }).then(r => { 2941cb0ef41Sopenharmony_ci assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk'); 2951cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should not have been called again'); 2961cb0ef41Sopenharmony_ci return delay(10); 2971cb0ef41Sopenharmony_ci }).then(() => { 2981cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called exactly once'); 2991cb0ef41Sopenharmony_ci }); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once on a non-empty stream read from before start fulfills'); 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_cipromise_test(() => { 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci let pullCount = 0; 3061cb0ef41Sopenharmony_ci const startPromise = Promise.resolve(); 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 3091cb0ef41Sopenharmony_ci start(c) { 3101cb0ef41Sopenharmony_ci c.enqueue('a'); 3111cb0ef41Sopenharmony_ci }, 3121cb0ef41Sopenharmony_ci pull() { 3131cb0ef41Sopenharmony_ci pullCount++; 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci }); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 3181cb0ef41Sopenharmony_ci assert_equals(pullCount, 0, 'pull should not be called once start finishes, since the queue is full'); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci const read = rs.getReader().read(); 3211cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'calling read() should cause pull to be called immediately'); 3221cb0ef41Sopenharmony_ci return read; 3231cb0ef41Sopenharmony_ci }).then(r => { 3241cb0ef41Sopenharmony_ci assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk'); 3251cb0ef41Sopenharmony_ci return delay(10); 3261cb0ef41Sopenharmony_ci }).then(() => { 3271cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called exactly once'); 3281cb0ef41Sopenharmony_ci }); 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once on a non-empty stream read from after start fulfills'); 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_cipromise_test(() => { 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci let pullCount = 0; 3351cb0ef41Sopenharmony_ci let controller; 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 3381cb0ef41Sopenharmony_ci start(c) { 3391cb0ef41Sopenharmony_ci controller = c; 3401cb0ef41Sopenharmony_ci }, 3411cb0ef41Sopenharmony_ci pull() { 3421cb0ef41Sopenharmony_ci ++pullCount; 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci }); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci const reader = rs.getReader(); 3471cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 3481cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should have been called once by the time the stream starts'); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci controller.enqueue('a'); 3511cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should not have been called again after enqueue'); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci return reader.read(); 3541cb0ef41Sopenharmony_ci }).then(() => { 3551cb0ef41Sopenharmony_ci assert_equals(pullCount, 2, 'pull should have been called again after read'); 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci return delay(10); 3581cb0ef41Sopenharmony_ci }).then(() => { 3591cb0ef41Sopenharmony_ci assert_equals(pullCount, 2, 'pull should be called exactly twice'); 3601cb0ef41Sopenharmony_ci }); 3611cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull in reaction to read()ing the last chunk, if not draining'); 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_cipromise_test(() => { 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci let pullCount = 0; 3661cb0ef41Sopenharmony_ci let controller; 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 3691cb0ef41Sopenharmony_ci start(c) { 3701cb0ef41Sopenharmony_ci controller = c; 3711cb0ef41Sopenharmony_ci }, 3721cb0ef41Sopenharmony_ci pull() { 3731cb0ef41Sopenharmony_ci ++pullCount; 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci }); 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_ci const reader = rs.getReader(); 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 3801cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should have been called once by the time the stream starts'); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci controller.enqueue('a'); 3831cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should not have been called again after enqueue'); 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci controller.close(); 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci return reader.read(); 3881cb0ef41Sopenharmony_ci }).then(() => { 3891cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should not have been called a second time after read'); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci return delay(10); 3921cb0ef41Sopenharmony_ci }).then(() => { 3931cb0ef41Sopenharmony_ci assert_equals(pullCount, 1, 'pull should be called exactly once'); 3941cb0ef41Sopenharmony_ci }); 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining'); 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_cipromise_test(() => { 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci let resolve; 4011cb0ef41Sopenharmony_ci let returnedPromise; 4021cb0ef41Sopenharmony_ci let timesCalled = 0; 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 4051cb0ef41Sopenharmony_ci pull(c) { 4061cb0ef41Sopenharmony_ci c.enqueue(++timesCalled); 4071cb0ef41Sopenharmony_ci returnedPromise = new Promise(r => resolve = r); 4081cb0ef41Sopenharmony_ci return returnedPromise; 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci }); 4111cb0ef41Sopenharmony_ci const reader = rs.getReader(); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci return reader.read() 4141cb0ef41Sopenharmony_ci .then(result1 => { 4151cb0ef41Sopenharmony_ci assert_equals(timesCalled, 1, 4161cb0ef41Sopenharmony_ci 'pull should have been called once after start, but not yet have been called a second time'); 4171cb0ef41Sopenharmony_ci assert_object_equals(result1, { value: 1, done: false }, 'read() should fulfill with the enqueued value'); 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci return delay(10); 4201cb0ef41Sopenharmony_ci }).then(() => { 4211cb0ef41Sopenharmony_ci assert_equals(timesCalled, 1, 'after 10 ms, pull should still only have been called once'); 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci resolve(); 4241cb0ef41Sopenharmony_ci return returnedPromise; 4251cb0ef41Sopenharmony_ci }).then(() => { 4261cb0ef41Sopenharmony_ci assert_equals(timesCalled, 2, 4271cb0ef41Sopenharmony_ci 'after the promise returned by pull is fulfilled, pull should be called a second time'); 4281cb0ef41Sopenharmony_ci }); 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull until the previous pull call\'s promise fulfills'); 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_cipromise_test(() => { 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci let timesCalled = 0; 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci const rs = new ReadableStream( 4371cb0ef41Sopenharmony_ci { 4381cb0ef41Sopenharmony_ci start(c) { 4391cb0ef41Sopenharmony_ci c.enqueue('a'); 4401cb0ef41Sopenharmony_ci c.enqueue('b'); 4411cb0ef41Sopenharmony_ci c.enqueue('c'); 4421cb0ef41Sopenharmony_ci }, 4431cb0ef41Sopenharmony_ci pull() { 4441cb0ef41Sopenharmony_ci ++timesCalled; 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci }, 4471cb0ef41Sopenharmony_ci { 4481cb0ef41Sopenharmony_ci size() { 4491cb0ef41Sopenharmony_ci return 1; 4501cb0ef41Sopenharmony_ci }, 4511cb0ef41Sopenharmony_ci highWaterMark: Infinity 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci ); 4541cb0ef41Sopenharmony_ci const reader = rs.getReader(); 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci return flushAsyncEvents().then(() => { 4571cb0ef41Sopenharmony_ci return reader.read(); 4581cb0ef41Sopenharmony_ci }).then(result1 => { 4591cb0ef41Sopenharmony_ci assert_object_equals(result1, { value: 'a', done: false }, 'first chunk should be as expected'); 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci return reader.read(); 4621cb0ef41Sopenharmony_ci }).then(result2 => { 4631cb0ef41Sopenharmony_ci assert_object_equals(result2, { value: 'b', done: false }, 'second chunk should be as expected'); 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci return reader.read(); 4661cb0ef41Sopenharmony_ci }).then(result3 => { 4671cb0ef41Sopenharmony_ci assert_object_equals(result3, { value: 'c', done: false }, 'third chunk should be as expected'); 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci return delay(10); 4701cb0ef41Sopenharmony_ci }).then(() => { 4711cb0ef41Sopenharmony_ci // Once for after start, and once for every read. 4721cb0ef41Sopenharmony_ci assert_equals(timesCalled, 4, 'pull() should be called exactly four times'); 4731cb0ef41Sopenharmony_ci }); 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci}, 'ReadableStream: should pull after start, and after every read'); 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_cipromise_test(() => { 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci let timesCalled = 0; 4801cb0ef41Sopenharmony_ci const startPromise = Promise.resolve(); 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 4831cb0ef41Sopenharmony_ci start(c) { 4841cb0ef41Sopenharmony_ci c.enqueue('a'); 4851cb0ef41Sopenharmony_ci c.close(); 4861cb0ef41Sopenharmony_ci return startPromise; 4871cb0ef41Sopenharmony_ci }, 4881cb0ef41Sopenharmony_ci pull() { 4891cb0ef41Sopenharmony_ci ++timesCalled; 4901cb0ef41Sopenharmony_ci } 4911cb0ef41Sopenharmony_ci }); 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci const reader = rs.getReader(); 4941cb0ef41Sopenharmony_ci return startPromise.then(() => { 4951cb0ef41Sopenharmony_ci assert_equals(timesCalled, 0, 'after start finishes, pull should not have been called'); 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci return reader.read(); 4981cb0ef41Sopenharmony_ci }).then(() => { 4991cb0ef41Sopenharmony_ci assert_equals(timesCalled, 0, 'reading should not have triggered a pull call'); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci return reader.closed; 5021cb0ef41Sopenharmony_ci }).then(() => { 5031cb0ef41Sopenharmony_ci assert_equals(timesCalled, 0, 'stream should have closed with still no calls to pull'); 5041cb0ef41Sopenharmony_ci }); 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull after start if the stream is now closed'); 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_cipromise_test(() => { 5091cb0ef41Sopenharmony_ci 5101cb0ef41Sopenharmony_ci let timesCalled = 0; 5111cb0ef41Sopenharmony_ci let resolve; 5121cb0ef41Sopenharmony_ci const ready = new Promise(r => resolve = r); 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_ci new ReadableStream( 5151cb0ef41Sopenharmony_ci { 5161cb0ef41Sopenharmony_ci start() {}, 5171cb0ef41Sopenharmony_ci pull(c) { 5181cb0ef41Sopenharmony_ci c.enqueue(++timesCalled); 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci if (timesCalled === 4) { 5211cb0ef41Sopenharmony_ci resolve(); 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci }, 5251cb0ef41Sopenharmony_ci { 5261cb0ef41Sopenharmony_ci size() { 5271cb0ef41Sopenharmony_ci return 1; 5281cb0ef41Sopenharmony_ci }, 5291cb0ef41Sopenharmony_ci highWaterMark: 4 5301cb0ef41Sopenharmony_ci } 5311cb0ef41Sopenharmony_ci ); 5321cb0ef41Sopenharmony_ci 5331cb0ef41Sopenharmony_ci return ready.then(() => { 5341cb0ef41Sopenharmony_ci // after start: size = 0, pull() 5351cb0ef41Sopenharmony_ci // after enqueue(1): size = 1, pull() 5361cb0ef41Sopenharmony_ci // after enqueue(2): size = 2, pull() 5371cb0ef41Sopenharmony_ci // after enqueue(3): size = 3, pull() 5381cb0ef41Sopenharmony_ci // after enqueue(4): size = 4, do not pull 5391cb0ef41Sopenharmony_ci assert_equals(timesCalled, 4, 'pull() should have been called four times'); 5401cb0ef41Sopenharmony_ci }); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull after enqueueing from inside pull (with no read requests), if strategy allows'); 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_cipromise_test(() => { 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci let pullCalled = false; 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 5491cb0ef41Sopenharmony_ci pull(c) { 5501cb0ef41Sopenharmony_ci pullCalled = true; 5511cb0ef41Sopenharmony_ci c.close(); 5521cb0ef41Sopenharmony_ci } 5531cb0ef41Sopenharmony_ci }); 5541cb0ef41Sopenharmony_ci 5551cb0ef41Sopenharmony_ci const reader = rs.getReader(); 5561cb0ef41Sopenharmony_ci return reader.closed.then(() => { 5571cb0ef41Sopenharmony_ci assert_true(pullCalled); 5581cb0ef41Sopenharmony_ci }); 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to close a stream.'); 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_cipromise_test(t => { 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci const controllerError = { name: 'controller error' }; 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 5671cb0ef41Sopenharmony_ci pull(c) { 5681cb0ef41Sopenharmony_ci c.error(controllerError); 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci }); 5711cb0ef41Sopenharmony_ci 5721cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, controllerError, rs.getReader().closed); 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to error a stream.'); 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_cipromise_test(t => { 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci const controllerError = { name: 'controller error' }; 5791cb0ef41Sopenharmony_ci const thrownError = { name: 'thrown error' }; 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 5821cb0ef41Sopenharmony_ci pull(c) { 5831cb0ef41Sopenharmony_ci c.error(controllerError); 5841cb0ef41Sopenharmony_ci throw thrownError; 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci }); 5871cb0ef41Sopenharmony_ci 5881cb0ef41Sopenharmony_ci return promise_rejects_exactly(t, controllerError, rs.getReader().closed); 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to error a stream and throw.'); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_citest(() => { 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ci let startCalled = false; 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci new ReadableStream({ 5971cb0ef41Sopenharmony_ci start(c) { 5981cb0ef41Sopenharmony_ci assert_equals(c.enqueue('a'), undefined, 'the first enqueue should return undefined'); 5991cb0ef41Sopenharmony_ci c.close(); 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => c.enqueue('b'), 'enqueue after close should throw a TypeError'); 6021cb0ef41Sopenharmony_ci startCalled = true; 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci }); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci assert_true(startCalled); 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci}, 'ReadableStream: enqueue should throw when the stream is readable but draining'); 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_citest(() => { 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci let startCalled = false; 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci new ReadableStream({ 6151cb0ef41Sopenharmony_ci start(c) { 6161cb0ef41Sopenharmony_ci c.close(); 6171cb0ef41Sopenharmony_ci 6181cb0ef41Sopenharmony_ci assert_throws_js(TypeError, () => c.enqueue('a'), 'enqueue after close should throw a TypeError'); 6191cb0ef41Sopenharmony_ci startCalled = true; 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci }); 6221cb0ef41Sopenharmony_ci 6231cb0ef41Sopenharmony_ci assert_true(startCalled); 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci}, 'ReadableStream: enqueue should throw when the stream is closed'); 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_cipromise_test(() => { 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci let startCalled = 0; 6301cb0ef41Sopenharmony_ci let pullCalled = 0; 6311cb0ef41Sopenharmony_ci let cancelCalled = 0; 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci /* eslint-disable no-use-before-define */ 6341cb0ef41Sopenharmony_ci class Source { 6351cb0ef41Sopenharmony_ci start(c) { 6361cb0ef41Sopenharmony_ci startCalled++; 6371cb0ef41Sopenharmony_ci assert_equals(this, theSource, 'start() should be called with the correct this'); 6381cb0ef41Sopenharmony_ci c.enqueue('a'); 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci 6411cb0ef41Sopenharmony_ci pull() { 6421cb0ef41Sopenharmony_ci pullCalled++; 6431cb0ef41Sopenharmony_ci assert_equals(this, theSource, 'pull() should be called with the correct this'); 6441cb0ef41Sopenharmony_ci } 6451cb0ef41Sopenharmony_ci 6461cb0ef41Sopenharmony_ci cancel() { 6471cb0ef41Sopenharmony_ci cancelCalled++; 6481cb0ef41Sopenharmony_ci assert_equals(this, theSource, 'cancel() should be called with the correct this'); 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci /* eslint-enable no-use-before-define */ 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci const theSource = new Source(); 6541cb0ef41Sopenharmony_ci theSource.debugName = 'the source object passed to the constructor'; // makes test failures easier to diagnose 6551cb0ef41Sopenharmony_ci 6561cb0ef41Sopenharmony_ci const rs = new ReadableStream(theSource); 6571cb0ef41Sopenharmony_ci const reader = rs.getReader(); 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci return reader.read().then(() => { 6601cb0ef41Sopenharmony_ci reader.releaseLock(); 6611cb0ef41Sopenharmony_ci rs.cancel(); 6621cb0ef41Sopenharmony_ci assert_equals(startCalled, 1); 6631cb0ef41Sopenharmony_ci assert_equals(pullCalled, 1); 6641cb0ef41Sopenharmony_ci assert_equals(cancelCalled, 1); 6651cb0ef41Sopenharmony_ci return rs.getReader().closed; 6661cb0ef41Sopenharmony_ci }); 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci}, 'ReadableStream: should call underlying source methods as methods'); 6691cb0ef41Sopenharmony_ci 6701cb0ef41Sopenharmony_citest(() => { 6711cb0ef41Sopenharmony_ci new ReadableStream({ 6721cb0ef41Sopenharmony_ci start(c) { 6731cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, 10, 'desiredSize must start at highWaterMark'); 6741cb0ef41Sopenharmony_ci c.close(); 6751cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, 0, 'after closing, desiredSize must be 0'); 6761cb0ef41Sopenharmony_ci } 6771cb0ef41Sopenharmony_ci }, { 6781cb0ef41Sopenharmony_ci highWaterMark: 10 6791cb0ef41Sopenharmony_ci }); 6801cb0ef41Sopenharmony_ci}, 'ReadableStream: desiredSize when closed'); 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_citest(() => { 6831cb0ef41Sopenharmony_ci new ReadableStream({ 6841cb0ef41Sopenharmony_ci start(c) { 6851cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, 10, 'desiredSize must start at highWaterMark'); 6861cb0ef41Sopenharmony_ci c.error(); 6871cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, null, 'after erroring, desiredSize must be null'); 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci }, { 6901cb0ef41Sopenharmony_ci highWaterMark: 10 6911cb0ef41Sopenharmony_ci }); 6921cb0ef41Sopenharmony_ci}, 'ReadableStream: desiredSize when errored'); 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_citest(() => { 6951cb0ef41Sopenharmony_ci class Subclass extends ReadableStream { 6961cb0ef41Sopenharmony_ci extraFunction() { 6971cb0ef41Sopenharmony_ci return true; 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci } 7001cb0ef41Sopenharmony_ci assert_equals( 7011cb0ef41Sopenharmony_ci Object.getPrototypeOf(Subclass.prototype), ReadableStream.prototype, 7021cb0ef41Sopenharmony_ci 'Subclass.prototype\'s prototype should be ReadableStream.prototype'); 7031cb0ef41Sopenharmony_ci assert_equals(Object.getPrototypeOf(Subclass), ReadableStream, 7041cb0ef41Sopenharmony_ci 'Subclass\'s prototype should be ReadableStream'); 7051cb0ef41Sopenharmony_ci const sub = new Subclass(); 7061cb0ef41Sopenharmony_ci assert_true(sub instanceof ReadableStream, 7071cb0ef41Sopenharmony_ci 'Subclass object should be an instance of ReadableStream'); 7081cb0ef41Sopenharmony_ci assert_true(sub instanceof Subclass, 7091cb0ef41Sopenharmony_ci 'Subclass object should be an instance of Subclass'); 7101cb0ef41Sopenharmony_ci const lockedGetter = Object.getOwnPropertyDescriptor( 7111cb0ef41Sopenharmony_ci ReadableStream.prototype, 'locked').get; 7121cb0ef41Sopenharmony_ci assert_equals(lockedGetter.call(sub), sub.locked, 7131cb0ef41Sopenharmony_ci 'Subclass object should pass brand check'); 7141cb0ef41Sopenharmony_ci assert_true(sub.extraFunction(), 7151cb0ef41Sopenharmony_ci 'extraFunction() should be present on Subclass object'); 7161cb0ef41Sopenharmony_ci}, 'Subclassing ReadableStream should work'); 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_citest(() => { 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ci let startCalled = false; 7211cb0ef41Sopenharmony_ci new ReadableStream({ 7221cb0ef41Sopenharmony_ci start(c) { 7231cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, 1); 7241cb0ef41Sopenharmony_ci c.enqueue('a'); 7251cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, 0); 7261cb0ef41Sopenharmony_ci c.enqueue('b'); 7271cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, -1); 7281cb0ef41Sopenharmony_ci c.enqueue('c'); 7291cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, -2); 7301cb0ef41Sopenharmony_ci c.enqueue('d'); 7311cb0ef41Sopenharmony_ci assert_equals(c.desiredSize, -3); 7321cb0ef41Sopenharmony_ci c.enqueue('e'); 7331cb0ef41Sopenharmony_ci startCalled = true; 7341cb0ef41Sopenharmony_ci } 7351cb0ef41Sopenharmony_ci }); 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci assert_true(startCalled); 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci}, 'ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue'); 7401cb0ef41Sopenharmony_ci 7411cb0ef41Sopenharmony_cipromise_test(() => { 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci let controller; 7441cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 7451cb0ef41Sopenharmony_ci start(c) { 7461cb0ef41Sopenharmony_ci controller = c; 7471cb0ef41Sopenharmony_ci } 7481cb0ef41Sopenharmony_ci }); 7491cb0ef41Sopenharmony_ci const reader = rs.getReader(); 7501cb0ef41Sopenharmony_ci 7511cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 1, 'desiredSize should start at 1'); 7521cb0ef41Sopenharmony_ci controller.enqueue('a'); 7531cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 0, 'desiredSize should decrease to 0 after first enqueue'); 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci return reader.read().then(result1 => { 7561cb0ef41Sopenharmony_ci assert_object_equals(result1, { value: 'a', done: false }, 'first chunk read should be correct'); 7571cb0ef41Sopenharmony_ci 7581cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the first read'); 7591cb0ef41Sopenharmony_ci controller.enqueue('b'); 7601cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the second enqueue'); 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_ci return reader.read(); 7631cb0ef41Sopenharmony_ci }).then(result2 => { 7641cb0ef41Sopenharmony_ci assert_object_equals(result2, { value: 'b', done: false }, 'second chunk read should be correct'); 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the second read'); 7671cb0ef41Sopenharmony_ci controller.enqueue('c'); 7681cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the third enqueue'); 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci return reader.read(); 7711cb0ef41Sopenharmony_ci }).then(result3 => { 7721cb0ef41Sopenharmony_ci assert_object_equals(result3, { value: 'c', done: false }, 'third chunk read should be correct'); 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the third read'); 7751cb0ef41Sopenharmony_ci controller.enqueue('d'); 7761cb0ef41Sopenharmony_ci assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the fourth enqueue'); 7771cb0ef41Sopenharmony_ci }); 7781cb0ef41Sopenharmony_ci 7791cb0ef41Sopenharmony_ci}, 'ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately'); 7801cb0ef41Sopenharmony_ci 7811cb0ef41Sopenharmony_cipromise_test(t => { 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ci const randomSource = new RandomPushSource(8); 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci const rs = new ReadableStream({ 7861cb0ef41Sopenharmony_ci start(c) { 7871cb0ef41Sopenharmony_ci assert_equals(typeof c, 'object', 'c should be an object in start'); 7881cb0ef41Sopenharmony_ci assert_equals(typeof c.enqueue, 'function', 'enqueue should be a function in start'); 7891cb0ef41Sopenharmony_ci assert_equals(typeof c.close, 'function', 'close should be a function in start'); 7901cb0ef41Sopenharmony_ci assert_equals(typeof c.error, 'function', 'error should be a function in start'); 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_ci randomSource.ondata = t.step_func(chunk => { 7931cb0ef41Sopenharmony_ci if (!c.enqueue(chunk) <= 0) { 7941cb0ef41Sopenharmony_ci randomSource.readStop(); 7951cb0ef41Sopenharmony_ci } 7961cb0ef41Sopenharmony_ci }); 7971cb0ef41Sopenharmony_ci 7981cb0ef41Sopenharmony_ci randomSource.onend = c.close.bind(c); 7991cb0ef41Sopenharmony_ci randomSource.onerror = c.error.bind(c); 8001cb0ef41Sopenharmony_ci }, 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci pull(c) { 8031cb0ef41Sopenharmony_ci assert_equals(typeof c, 'object', 'c should be an object in pull'); 8041cb0ef41Sopenharmony_ci assert_equals(typeof c.enqueue, 'function', 'enqueue should be a function in pull'); 8051cb0ef41Sopenharmony_ci assert_equals(typeof c.close, 'function', 'close should be a function in pull'); 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci randomSource.readStart(); 8081cb0ef41Sopenharmony_ci } 8091cb0ef41Sopenharmony_ci }); 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci return readableStreamToArray(rs).then(chunks => { 8121cb0ef41Sopenharmony_ci assert_equals(chunks.length, 8, '8 chunks should be read'); 8131cb0ef41Sopenharmony_ci for (const chunk of chunks) { 8141cb0ef41Sopenharmony_ci assert_equals(chunk.length, 128, 'chunk should have 128 bytes'); 8151cb0ef41Sopenharmony_ci } 8161cb0ef41Sopenharmony_ci }); 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting a random push source'); 8191cb0ef41Sopenharmony_ci 8201cb0ef41Sopenharmony_cipromise_test(() => { 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci const rs = sequentialReadableStream(10); 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci return readableStreamToArray(rs).then(chunks => { 8251cb0ef41Sopenharmony_ci assert_true(rs.source.closed, 'source should be closed after all chunks are read'); 8261cb0ef41Sopenharmony_ci assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read'); 8271cb0ef41Sopenharmony_ci }); 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting a sync pull source'); 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_cipromise_test(() => { 8321cb0ef41Sopenharmony_ci 8331cb0ef41Sopenharmony_ci const rs = sequentialReadableStream(10, { async: true }); 8341cb0ef41Sopenharmony_ci 8351cb0ef41Sopenharmony_ci return readableStreamToArray(rs).then(chunks => { 8361cb0ef41Sopenharmony_ci assert_true(rs.source.closed, 'source should be closed after all chunks are read'); 8371cb0ef41Sopenharmony_ci assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read'); 8381cb0ef41Sopenharmony_ci }); 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting an async pull source'); 841