61 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import {BINARY_ENCODINGS} from '../arguments/encoding-option.js';
 | |
| import {TRANSFORM_TYPES} from '../stdio/type.js';
 | |
| import {verboseLog, serializeVerboseMessage} from './log.js';
 | |
| import {isFullVerbose} from './values.js';
 | |
| 
 | |
| // `ignore` opts-out of `verbose` for a specific stream.
 | |
| // `ipc` cannot use piping.
 | |
| // `inherit` would result in double printing.
 | |
| // They can also lead to double printing when passing file descriptor integers or `process.std*`.
 | |
| // This only leaves with `pipe` and `overlapped`.
 | |
| export const shouldLogOutput = ({stdioItems, encoding, verboseInfo, fdNumber}) => fdNumber !== 'all'
 | |
| 	&& isFullVerbose(verboseInfo, fdNumber)
 | |
| 	&& !BINARY_ENCODINGS.has(encoding)
 | |
| 	&& fdUsesVerbose(fdNumber)
 | |
| 	&& (stdioItems.some(({type, value}) => type === 'native' && PIPED_STDIO_VALUES.has(value))
 | |
| 	|| stdioItems.every(({type}) => TRANSFORM_TYPES.has(type)));
 | |
| 
 | |
| // Printing input streams would be confusing.
 | |
| // Files and streams can produce big outputs, which we don't want to print.
 | |
| // We could print `stdio[3+]` but it often is redirected to files and streams, with the same issue.
 | |
| // So we only print stdout and stderr.
 | |
| const fdUsesVerbose = fdNumber => fdNumber === 1 || fdNumber === 2;
 | |
| 
 | |
| const PIPED_STDIO_VALUES = new Set(['pipe', 'overlapped']);
 | |
| 
 | |
| // `verbose: 'full'` printing logic with async methods
 | |
| export const logLines = async (linesIterable, stream, fdNumber, verboseInfo) => {
 | |
| 	for await (const line of linesIterable) {
 | |
| 		if (!isPipingStream(stream)) {
 | |
| 			logLine(line, fdNumber, verboseInfo);
 | |
| 		}
 | |
| 	}
 | |
| };
 | |
| 
 | |
| // `verbose: 'full'` printing logic with sync methods
 | |
| export const logLinesSync = (linesArray, fdNumber, verboseInfo) => {
 | |
| 	for (const line of linesArray) {
 | |
| 		logLine(line, fdNumber, verboseInfo);
 | |
| 	}
 | |
| };
 | |
| 
 | |
| // When `subprocess.stdout|stderr.pipe()` is called, `verbose` becomes a noop.
 | |
| // This prevents the following problems:
 | |
| //  - `.pipe()` achieves the same result as using `stdout: 'inherit'`, `stdout: stream`, etc. which also make `verbose` a noop.
 | |
| //    For example, `subprocess.stdout.pipe(process.stdin)` would print each line twice.
 | |
| //  - When chaining subprocesses with `subprocess.pipe(otherSubprocess)`, only the last one should print its output.
 | |
| // Detecting whether `.pipe()` is impossible without monkey-patching it, so we use the following undocumented property.
 | |
| // This is not a critical behavior since changes of the following property would only make `verbose` more verbose.
 | |
| const isPipingStream = stream => stream._readableState.pipes.length > 0;
 | |
| 
 | |
| // When `verbose` is `full`, print stdout|stderr
 | |
| const logLine = (line, fdNumber, verboseInfo) => {
 | |
| 	const verboseMessage = serializeVerboseMessage(line);
 | |
| 	verboseLog({
 | |
| 		type: 'output',
 | |
| 		verboseMessage,
 | |
| 		fdNumber,
 | |
| 		verboseInfo,
 | |
| 	});
 | |
| };
 |