ernalBinding('mksnapshot').cleanups.push(function cleanupStdout() {
    stdout._destroy = stdoutDestroy;
    stdout.destroy();
    process.removeListener('SIGWINCH', refreshStdoutOnSigWinch);
    stdout = undefined;
  });
  return stdout;
}

function getStderr() {
  if (stderr) return stderr;
  stderr = createWritableStdioStream(2);
  stderr.destroySoon = stderr.destroy;
  stderrDestroy = stderr._destroy;
  // Override _destroy so that the fd is never actually closed.
  stderr._destroy = dummyDestroy;
  if (stderr.isTTY) {
    process.on('SIGWINCH', refreshStderrOnSigWinch);
  }
  internalBinding('mksnapshot').cleanups.push(function cleanupStderr() {
    stderr._destroy = stderrDestroy;
    stderr.destroy();
    process.removeListener('SIGWINCH', refreshStderrOnSigWinch);
    stderr = undefined;
  });
  return stderr;
}

function getStdin() {
  if (stdin) return stdin;
  const fd = 0;

  switch (guessHandleType(fd)) {
    case 'TTY': {
      const tty = require('tty');
      stdin = new tty.ReadStream(fd);
      break;
    }

    case 'FILE': {
      const fs = require('fs');
      stdin = new fs.ReadStream(null, { fd: fd, autoClose: false });
      break;
    }

    case 'PIPE':
    case 'TCP': {
      const net = require('net');

      // It could be that process has been started with an IPC channel
      // sitting on fd=0, in such case the pipe for this fd is already
      // present and creating a new one will lead to the assertion failure
      // in libuv.
      if (process.channel && process.channel.fd === fd) {
        stdin = new net.Socket({
          handle: process.channel,
          readable: true,
          writable: false,
          manualStart: true
        });
      } else {
        stdin = new net.Socket({
          fd: fd,
          readable: true,
          writable: false,
          manualStart: true
        });
      }
      // Make sure the stdin can't be `.end()`-ed
      stdin._writableState.ended = true;
      break;
    }

    default: {
      // Provide a dummy contentless input for e.g. non-console
      // Windows applications.
      const { Readable } = require('stream');
      stdin = new Readable({ read() {} });
      stdin.push(null);
    }
  }

  // For supporting legacy API we put the FD here.
  stdin.fd = fd;

  // `stdin` starts out life in a paused state, but node doesn't
  // know yet. Explicitly to readStop() it to put it in the
  // not-reading state.
  if (stdin._handle && stdin._handle.readStop) {
    stdin._handle.reading = false;
    stdin._readableState.reading = false;
    stdin._handle.readStop();
  }

  // If the user calls stdin.pause(), then we need to stop reading
  // once the stream implementation does so (one nextTick later),
  // so that the process can close down.
  stdin.on('pause', () => {
    process.nextTick(onpause);
  });

  function onpause() {
    if (!stdin._handle)
      return;
    if (stdin._handle.reading && !stdin.readableFlowing) {
      stdin._readableState.reading = false;
      stdin._handle.reading = false;
      stdin._handle.readStop();
    }
  }

  internalBinding('mksnapshot').cleanups.push(function cleanupStdin() {
    stdin.destroy();
    stdin = undefined;
  });
  return stdin;
}

// Used by internal tests.
rawMethods.resetStdioForTesting = function() {
  stdin = undefined;
  stdout = undefined;
  stderr = undefined;
};
