|
6 | 6 | ArrayBufferPrototypeSlice,
|
7 | 7 | ArrayPrototypePush,
|
8 | 8 | ArrayPrototypeShift,
|
| 9 | + Boolean, |
9 | 10 | DataView,
|
10 | 11 | FunctionPrototypeBind,
|
11 | 12 | FunctionPrototypeCall,
|
@@ -110,6 +111,8 @@ const {
|
110 | 111 | nonOpCancel,
|
111 | 112 | nonOpPull,
|
112 | 113 | nonOpStart,
|
| 114 | + getIterator, |
| 115 | + iteratorNext, |
113 | 116 | kType,
|
114 | 117 | kState,
|
115 | 118 | } = require('internal/webstreams/util');
|
@@ -312,6 +315,10 @@ class ReadableStream {
|
312 | 315 | return isReadableStreamLocked(this);
|
313 | 316 | }
|
314 | 317 |
|
| 318 | + static from(iterable) { |
| 319 | + return readableStreamFromIterable(iterable); |
| 320 | + } |
| 321 | + |
315 | 322 | /**
|
316 | 323 | * @param {any} [reason]
|
317 | 324 | * @returns { Promise<void> }
|
@@ -1248,6 +1255,75 @@ const isReadableStreamBYOBReader =
|
1248 | 1255 |
|
1249 | 1256 | // ---- ReadableStream Implementation
|
1250 | 1257 |
|
| 1258 | +function readableStreamFromIterable(iterable) { |
| 1259 | + let stream; |
| 1260 | + const iteratorRecord = getIterator(iterable, 'async'); |
| 1261 | + |
| 1262 | + const startAlgorithm = nonOpStart; |
| 1263 | + |
| 1264 | + function pullAlgorithm() { |
| 1265 | + let nextResult; |
| 1266 | + try { |
| 1267 | + nextResult = iteratorNext(iteratorRecord); |
| 1268 | + } catch (error) { |
| 1269 | + return PromiseReject(error); |
| 1270 | + } |
| 1271 | + const nextPromise = PromiseResolve(nextResult); |
| 1272 | + return PromisePrototypeThen(nextPromise, (iterResult) => { |
| 1273 | + if (typeof iterResult !== 'object' || iterResult === null) { |
| 1274 | + throw new ERR_INVALID_STATE.TypeError( |
| 1275 | + 'The promise returned by the iterator.next() method must fulfill with an object'); |
| 1276 | + } |
| 1277 | + const done = Boolean(iterResult.done); |
| 1278 | + if (done) { |
| 1279 | + readableStreamDefaultControllerClose(stream[kState].controller); |
| 1280 | + } else { |
| 1281 | + readableStreamDefaultControllerEnqueue(stream[kState].controller, iterResult.value); |
| 1282 | + } |
| 1283 | + }); |
| 1284 | + } |
| 1285 | + |
| 1286 | + function cancelAlgorithm(reason) { |
| 1287 | + const iterator = iteratorRecord.iterator; |
| 1288 | + let returnMethod; |
| 1289 | + try { |
| 1290 | + returnMethod = iterator.return; |
| 1291 | + } catch (error) { |
| 1292 | + return PromiseReject(error); |
| 1293 | + } |
| 1294 | + if (returnMethod === undefined) { |
| 1295 | + return PromiseResolve(); |
| 1296 | + } |
| 1297 | + let returnResult; |
| 1298 | + try { |
| 1299 | + returnResult = FunctionPrototypeCall(returnMethod, iterator, reason); |
| 1300 | + } catch (error) { |
| 1301 | + return PromiseReject(error); |
| 1302 | + } |
| 1303 | + const returnPromise = PromiseResolve(returnResult); |
| 1304 | + return PromisePrototypeThen(returnPromise, (iterResult) => { |
| 1305 | + if (typeof iterResult !== 'object' || iterResult === null) { |
| 1306 | + throw new ERR_INVALID_STATE.TypeError( |
| 1307 | + 'The promise returned by the iterator.return() method must fulfill with an object'); |
| 1308 | + } |
| 1309 | + return undefined; |
| 1310 | + }); |
| 1311 | + } |
| 1312 | + |
| 1313 | + stream = new ReadableStream({ |
| 1314 | + start: startAlgorithm, |
| 1315 | + pull: pullAlgorithm, |
| 1316 | + cancel: cancelAlgorithm, |
| 1317 | + }, { |
| 1318 | + size() { |
| 1319 | + return 1; |
| 1320 | + }, |
| 1321 | + highWaterMark: 0, |
| 1322 | + }); |
| 1323 | + |
| 1324 | + return stream; |
| 1325 | +} |
| 1326 | + |
1251 | 1327 | function readableStreamPipeTo(
|
1252 | 1328 | source,
|
1253 | 1329 | dest,
|
|
0 commit comments