11import { debuglog } from 'node:util' ;
22import isPlainObject from 'is-plain-obj' ;
33import { STANDARD_STREAMS_ALIASES } from '../utils/standard-stream.js' ;
4+ import { checkBooleanOption } from '../utils/options.js' ;
45
56// Some options can have different values for `stdout`/`stderr`/`fd3`.
67// This normalizes those to array of values.
@@ -27,12 +28,18 @@ const getStdioLength = ({stdio}) => Array.isArray(stdio)
2728 ? Math . max ( stdio . length , STANDARD_STREAMS_ALIASES . length )
2829 : STANDARD_STREAMS_ALIASES . length ;
2930
30- const normalizeFdSpecificValue = ( optionValue , optionArray , optionName , stdioLength ) => isPlainObject ( optionValue )
31- ? normalizeOptionObject ( optionValue , optionArray , optionName , stdioLength )
32- : optionArray . fill ( optionValue ) ;
31+ const normalizeFdSpecificValue = ( optionValue , optionArray , optionName , stdioLength ) => {
32+ if ( isPlainObject ( optionValue ) ) {
33+ return normalizeOptionObject ( optionValue , optionArray , optionName , stdioLength ) ;
34+ }
35+
36+ validateFdSpecificValue ( optionValue , optionName ) ;
37+ return optionArray . fill ( optionValue ) ;
38+ } ;
3339
3440const normalizeOptionObject = ( optionValue , optionArray , optionName , stdioLength ) => {
3541 for ( const fdName of Object . keys ( optionValue ) . sort ( compareFdName ) ) {
42+ validateFdSpecificValue ( optionValue [ fdName ] , optionName , `${ optionName } .${ fdName } ` ) ;
3643 for ( const fdNumber of parseFdName ( fdName , optionName , stdioLength ) ) {
3744 optionArray [ fdNumber ] = optionValue [ fdName ] ;
3845 }
@@ -93,6 +100,18 @@ const addDefaultValue = (optionArray, optionName) => optionArray.map(optionValue
93100 ? DEFAULT_OPTIONS [ optionName ]
94101 : optionValue ) ;
95102
103+ const BOOLEAN_FD_SPECIFIC_OPTIONS = new Set ( [ 'lines' , 'buffer' , 'stripFinalNewline' ] ) ;
104+
105+ // Wrong types must be reported instead of being silently coerced, e.g. a truthy string enabling the `buffer` option.
106+ // `undefined` uses the default value.
107+ const validateFdSpecificValue = ( optionValue , optionName , fullOptionName = optionName ) => {
108+ if ( BOOLEAN_FD_SPECIFIC_OPTIONS . has ( optionName ) ) {
109+ checkBooleanOption ( optionValue , fullOptionName ) ;
110+ } else if ( optionName === 'maxBuffer' && optionValue !== undefined && ( typeof optionValue !== 'number' || Number . isNaN ( optionValue ) ) ) {
111+ throw new TypeError ( `The \`${ fullOptionName } \` option must use a number.` ) ;
112+ }
113+ } ;
114+
96115// Default value for the `verbose` option
97116const verboseDefault = debuglog ( 'execa' ) . enabled ? 'full' : 'none' ;
98117
0 commit comments