11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  PromisePrototypeThen,
51cb0ef41Sopenharmony_ci  SymbolAsyncIterator,
61cb0ef41Sopenharmony_ci  SymbolIterator,
71cb0ef41Sopenharmony_ci} = primordials;
81cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst {
111cb0ef41Sopenharmony_ci  ERR_INVALID_ARG_TYPE,
121cb0ef41Sopenharmony_ci  ERR_STREAM_NULL_VALUES,
131cb0ef41Sopenharmony_ci} = require('internal/errors').codes;
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cifunction from(Readable, iterable, opts) {
161cb0ef41Sopenharmony_ci  let iterator;
171cb0ef41Sopenharmony_ci  if (typeof iterable === 'string' || iterable instanceof Buffer) {
181cb0ef41Sopenharmony_ci    return new Readable({
191cb0ef41Sopenharmony_ci      objectMode: true,
201cb0ef41Sopenharmony_ci      ...opts,
211cb0ef41Sopenharmony_ci      read() {
221cb0ef41Sopenharmony_ci        this.push(iterable);
231cb0ef41Sopenharmony_ci        this.push(null);
241cb0ef41Sopenharmony_ci      },
251cb0ef41Sopenharmony_ci    });
261cb0ef41Sopenharmony_ci  }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  let isAsync;
291cb0ef41Sopenharmony_ci  if (iterable && iterable[SymbolAsyncIterator]) {
301cb0ef41Sopenharmony_ci    isAsync = true;
311cb0ef41Sopenharmony_ci    iterator = iterable[SymbolAsyncIterator]();
321cb0ef41Sopenharmony_ci  } else if (iterable && iterable[SymbolIterator]) {
331cb0ef41Sopenharmony_ci    isAsync = false;
341cb0ef41Sopenharmony_ci    iterator = iterable[SymbolIterator]();
351cb0ef41Sopenharmony_ci  } else {
361cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable);
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  const readable = new Readable({
401cb0ef41Sopenharmony_ci    objectMode: true,
411cb0ef41Sopenharmony_ci    highWaterMark: 1,
421cb0ef41Sopenharmony_ci    // TODO(ronag): What options should be allowed?
431cb0ef41Sopenharmony_ci    ...opts,
441cb0ef41Sopenharmony_ci  });
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  // Flag to protect against _read
471cb0ef41Sopenharmony_ci  // being called before last iteration completion.
481cb0ef41Sopenharmony_ci  let reading = false;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  readable._read = function() {
511cb0ef41Sopenharmony_ci    if (!reading) {
521cb0ef41Sopenharmony_ci      reading = true;
531cb0ef41Sopenharmony_ci      next();
541cb0ef41Sopenharmony_ci    }
551cb0ef41Sopenharmony_ci  };
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  readable._destroy = function(error, cb) {
581cb0ef41Sopenharmony_ci    PromisePrototypeThen(
591cb0ef41Sopenharmony_ci      close(error),
601cb0ef41Sopenharmony_ci      () => process.nextTick(cb, error), // nextTick is here in case cb throws
611cb0ef41Sopenharmony_ci      (e) => process.nextTick(cb, e || error),
621cb0ef41Sopenharmony_ci    );
631cb0ef41Sopenharmony_ci  };
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  async function close(error) {
661cb0ef41Sopenharmony_ci    const hadError = (error !== undefined) && (error !== null);
671cb0ef41Sopenharmony_ci    const hasThrow = typeof iterator.throw === 'function';
681cb0ef41Sopenharmony_ci    if (hadError && hasThrow) {
691cb0ef41Sopenharmony_ci      const { value, done } = await iterator.throw(error);
701cb0ef41Sopenharmony_ci      await value;
711cb0ef41Sopenharmony_ci      if (done) {
721cb0ef41Sopenharmony_ci        return;
731cb0ef41Sopenharmony_ci      }
741cb0ef41Sopenharmony_ci    }
751cb0ef41Sopenharmony_ci    if (typeof iterator.return === 'function') {
761cb0ef41Sopenharmony_ci      const { value } = await iterator.return();
771cb0ef41Sopenharmony_ci      await value;
781cb0ef41Sopenharmony_ci    }
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  async function next() {
821cb0ef41Sopenharmony_ci    for (;;) {
831cb0ef41Sopenharmony_ci      try {
841cb0ef41Sopenharmony_ci        const { value, done } = isAsync ?
851cb0ef41Sopenharmony_ci          await iterator.next() :
861cb0ef41Sopenharmony_ci          iterator.next();
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci        if (done) {
891cb0ef41Sopenharmony_ci          readable.push(null);
901cb0ef41Sopenharmony_ci        } else {
911cb0ef41Sopenharmony_ci          const res = (value &&
921cb0ef41Sopenharmony_ci            typeof value.then === 'function') ?
931cb0ef41Sopenharmony_ci            await value :
941cb0ef41Sopenharmony_ci            value;
951cb0ef41Sopenharmony_ci          if (res === null) {
961cb0ef41Sopenharmony_ci            reading = false;
971cb0ef41Sopenharmony_ci            throw new ERR_STREAM_NULL_VALUES();
981cb0ef41Sopenharmony_ci          } else if (readable.push(res)) {
991cb0ef41Sopenharmony_ci            continue;
1001cb0ef41Sopenharmony_ci          } else {
1011cb0ef41Sopenharmony_ci            reading = false;
1021cb0ef41Sopenharmony_ci          }
1031cb0ef41Sopenharmony_ci        }
1041cb0ef41Sopenharmony_ci      } catch (err) {
1051cb0ef41Sopenharmony_ci        readable.destroy(err);
1061cb0ef41Sopenharmony_ci      }
1071cb0ef41Sopenharmony_ci      break;
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci  return readable;
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_cimodule.exports = from;
114