| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 | 'use strict';const path = require('path');const childProcess = require('child_process');const crossSpawn = require('cross-spawn');const stripFinalNewline = require('strip-final-newline');const npmRunPath = require('npm-run-path');const onetime = require('onetime');const makeError = require('./lib/error');const normalizeStdio = require('./lib/stdio');const {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} = require('./lib/kill');const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream');const {mergePromise, getSpawnedPromise} = require('./lib/promise');const {joinCommand, parseCommand, getEscapedCommand} = require('./lib/command');const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => {	const env = extendEnv ? {...process.env, ...envOption} : envOption;	if (preferLocal) {		return npmRunPath.env({env, cwd: localDir, execPath});	}	return env;};const handleArguments = (file, args, options = {}) => {	const parsed = crossSpawn._parse(file, args, options);	file = parsed.command;	args = parsed.args;	options = parsed.options;	options = {		maxBuffer: DEFAULT_MAX_BUFFER,		buffer: true,		stripFinalNewline: true,		extendEnv: true,		preferLocal: false,		localDir: options.cwd || process.cwd(),		execPath: process.execPath,		encoding: 'utf8',		reject: true,		cleanup: true,		all: false,		windowsHide: true,		...options	};	options.env = getEnv(options);	options.stdio = normalizeStdio(options);	if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') {		// #116		args.unshift('/q');	}	return {file, args, options, parsed};};const handleOutput = (options, value, error) => {	if (typeof value !== 'string' && !Buffer.isBuffer(value)) {		// When `execa.sync()` errors, we normalize it to '' to mimic `execa()`		return error === undefined ? undefined : '';	}	if (options.stripFinalNewline) {		return stripFinalNewline(value);	}	return value;};const execa = (file, args, options) => {	const parsed = handleArguments(file, args, options);	const command = joinCommand(file, args);	const escapedCommand = getEscapedCommand(file, args);	validateTimeout(parsed.options);	let spawned;	try {		spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options);	} catch (error) {		// Ensure the returned error is always both a promise and a child process		const dummySpawned = new childProcess.ChildProcess();		const errorPromise = Promise.reject(makeError({			error,			stdout: '',			stderr: '',			all: '',			command,			escapedCommand,			parsed,			timedOut: false,			isCanceled: false,			killed: false		}));		return mergePromise(dummySpawned, errorPromise);	}	const spawnedPromise = getSpawnedPromise(spawned);	const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise);	const processDone = setExitHandler(spawned, parsed.options, timedPromise);	const context = {isCanceled: false};	spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned));	spawned.cancel = spawnedCancel.bind(null, spawned, context);	const handlePromise = async () => {		const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone);		const stdout = handleOutput(parsed.options, stdoutResult);		const stderr = handleOutput(parsed.options, stderrResult);		const all = handleOutput(parsed.options, allResult);		if (error || exitCode !== 0 || signal !== null) {			const returnedError = makeError({				error,				exitCode,				signal,				stdout,				stderr,				all,				command,				escapedCommand,				parsed,				timedOut,				isCanceled: context.isCanceled,				killed: spawned.killed			});			if (!parsed.options.reject) {				return returnedError;			}			throw returnedError;		}		return {			command,			escapedCommand,			exitCode: 0,			stdout,			stderr,			all,			failed: false,			timedOut: false,			isCanceled: false,			killed: false		};	};	const handlePromiseOnce = onetime(handlePromise);	handleInput(spawned, parsed.options.input);	spawned.all = makeAllStream(spawned, parsed.options);	return mergePromise(spawned, handlePromiseOnce);};module.exports = execa;module.exports.sync = (file, args, options) => {	const parsed = handleArguments(file, args, options);	const command = joinCommand(file, args);	const escapedCommand = getEscapedCommand(file, args);	validateInputSync(parsed.options);	let result;	try {		result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options);	} catch (error) {		throw makeError({			error,			stdout: '',			stderr: '',			all: '',			command,			escapedCommand,			parsed,			timedOut: false,			isCanceled: false,			killed: false		});	}	const stdout = handleOutput(parsed.options, result.stdout, result.error);	const stderr = handleOutput(parsed.options, result.stderr, result.error);	if (result.error || result.status !== 0 || result.signal !== null) {		const error = makeError({			stdout,			stderr,			error: result.error,			signal: result.signal,			exitCode: result.status,			command,			escapedCommand,			parsed,			timedOut: result.error && result.error.code === 'ETIMEDOUT',			isCanceled: false,			killed: result.signal !== null		});		if (!parsed.options.reject) {			return error;		}		throw error;	}	return {		command,		escapedCommand,		exitCode: 0,		stdout,		stderr,		failed: false,		timedOut: false,		isCanceled: false,		killed: false	};};module.exports.command = (command, options) => {	const [file, ...args] = parseCommand(command);	return execa(file, args, options);};module.exports.commandSync = (command, options) => {	const [file, ...args] = parseCommand(command);	return execa.sync(file, args, options);};module.exports.node = (scriptPath, args, options = {}) => {	if (args && !Array.isArray(args) && typeof args === 'object') {		options = args;		args = [];	}	const stdio = normalizeStdio.node(options);	const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect'));	const {		nodePath = process.execPath,		nodeOptions = defaultExecArgv	} = options;	return execa(		nodePath,		[			...nodeOptions,			scriptPath,			...(Array.isArray(args) ? args : [])		],		{			...options,			stdin: undefined,			stdout: undefined,			stderr: undefined,			stdio,			shell: false		}	);};
 |