dateObject(options, "options");
  if (validateFunction(callback, "callback"), validateAbortSignal(options.signal, "options.signal"), callback = once(callback), isReadableStream(stream) || isWritableStream(stream))
    return eosWeb(stream, options, callback);
  if (!isNodeStream(stream))
    throw @makeErrorWithCode(118, "stream", ["ReadableStream", "WritableStream", "Stream"], stream);
  let readable = options.readable ?? isReadableNodeStream(stream), writable = options.writable ?? isWritableNodeStream(stream), wState = stream._writableState, rState = stream._readableState, onlegacyfinish = () => {
    if (!stream.writable)
      onfinish();
  }, willEmitClose = _willEmitClose(stream) && isReadableNodeStream(stream) === readable && isWritableNodeStream(stream) === writable, writableFinished = isWritableFinished(stream, !1), onfinish = () => {
    if (writableFinished = !0, stream.destroyed)
      willEmitClose = !1;
    if (willEmitClose && (!stream.readable || readable))
      return;
    if (!readable || readableFinished)
      callback.@call(stream);
  }, readableFinished = isReadableFinished(stream, !1), onend = () => {
    if (readableFinished = !0, stream.destroyed)
      willEmitClose = !1;
    if (willEmitClose && (!stream.writable || writable))
      return;
    if (!writable || writableFinished)
      callback.@call(stream);
  }, onerror = (err) => {
    callback.@call(stream, err);
  }, closed = isClosed(stream), onclose = () => {
    closed = !0;
    let errored = isWritableErrored(stream) || isReadableErrored(stream);
    if (errored && typeof errored !== "boolean")
      return callback.@call(stream, errored);
    if (readable && !readableFinished && isReadableNodeStream(stream, !0)) {
      if (!isReadableFinished(stream, !1))
        return callback.@call(stream, @makeErrorWithCode(230));
    }
    if (writable && !writableFinished) {
      if (!isWritableFinished(stream, !1))
        return callback.@call(stream, @makeErrorWithCode(230));
    }
    callback.@call(stream);
  }, onclosed = () => {
    closed = !0;
    let errored = isWritableErrored(stream) || isReadableErrored(stream);
    if (errored && typeof errored !== "boolean")
      return callback.@call(stream, errored);
    callback.@call(stream);
  }, onrequest = () => {
    stream.req.on("finish", onfinish);
  };
  if (isRequest(stream)) {
    if (stream.on("complete", onfinish), !willEmitClose)
      stream.on("abort", onclose);
    if (stream.req)
      onrequest();
    else
      stream.on("request", onrequest);
  } else if (writable && !wState)
    stream.on("end", onlegacyfinish), stream.on("close", onlegacyfinish);
  if (!willEmitClose && typeof stream.aborted === "boolean")
    stream.on("aborted", onclose);
  if (stream.on("end", onend), stream.on("finish", onfinish), options.error !== !1)
    stream.on("error", onerror);
  if (stream.on("close", onclose), closed)
    process.nextTick(onclose);
  else if (wState?.errorEmitted || rState?.errorEmitted) {
    if (!willEmitClose)
      process.nextTick(onclosed);
  } else if (!readable && (!willEmitClose || isReadable(stream)) && (writableFinished || isWritable(stream) === !1) && (wState == null || wState.pendingcb === @undefined || wState.pendingcb === 0))
    process.nextTick(onclosed);
  else if (!writable && (!willEmitClose || isWritable(stream)) && (readableFinished || isReadable(stream) === !1))
    process.nextTick(onclosed);
  else if (rState && stream.req && stream.aborted)
    process.nextTick(onclosed);
  let cleanup = () => {
    if (callback = nop, stream.removeListener("aborted", onclose), stream.removeListener("complete", onfinish), stream.removeListener("abort", onclose), stream.removeListener("request", onrequest), stream.req)
      stream.req.removeListener("finish", onfinish);
    stream.removeListener("end", onlegacyfinish), stream.removeListener("close", onlegacyfinish), stream.removeListener("finish", onfinish), stream.removeListener("end", onend), stream.removeListener("error", onerror), stream.removeListener("close", onclose);
  };
  if (options.signal && !closed) {
    let abort = () => {
      let endCallback = callback;
      cleanup(), endCallback.@call(stream, @makeAbortError(@undefined, { cause: options.signal.reason }));
    };
    if (options.signal.aborted)
      process.nextTick(abort);
    else {
      addAbortListener ??= (@getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3)).addAbortListener;
      let disposable = addAbortListener(options.signal, abort), originalCallback = callback;
      callback = once((...args) => {
        disposable[SymbolDispose](), originalCallback.@apply(stream, args);
      });
    }
  }
  return cleanup;
}
function eosWeb(stream, options, callback) {
  let isAborted = !1, abort = nop;
  if (options.signal)
    if (abort = () => {
      isAborted = !0, callback.@call(stream, @makeAbortError(@undefined, { cause: options.signal.reason }));
    }, options.signal.aborted)
      process.nextTick(abort);
    else {
      addAbortListener ??= (@getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3)).addAbortListener;
      let disposable = addAbortListener(options.signal, abort), originalCallback = callback;
      callback = once((...args) => {
        disposable[SymbolDispose](), originalCallback.@apply(stream, args);
      });
    }
  let resolverFn = (...args) => {
    if (!isAborted)
      process.nextTick(() => callback.@apply(stream, args));
  };
  return PromisePrototypeThen.@call(stream[kIsClosedPromise].promise, resolverFn, resolverFn), nop;
}
function finished(stream, opts) {
  let autoCleanup = !1;
  if (opts === null)
    opts = kEmptyObject;
  if (opts?.cleanup)
    validateBoolean(opts.cleanup, "cleanup"), autoCleanup = opts.cleanup;
  return new @Promise((resolve, reject) => {
    let cleanup = eos(stream, opts, (err) => {
      if (autoCleanup)
        cleanup();
      if (err)
        reject(err);
      else
        resolve();
    });
  });
}
eos.finished = finished;
$ = eos;
return $})

