@@ -249,15 +249,13 @@ const PIPE = (() => {
249249// `$node --abort-on-uncaught-exception $file child`
250250// the process aborts.
251251function childShouldThrowAndAbort ( ) {
252- let testCmd = '' ;
252+ const escapedArgs = escapePOSIXShell `" ${ process . argv [ 0 ] } " --abort-on-uncaught-exception " ${ process . argv [ 1 ] } " child` ;
253253 if ( ! isWindows ) {
254254 // Do not create core files, as it can take a lot of disk space on
255255 // continuous testing and developers' machines
256- testCmd + = 'ulimit -c 0 && ' ;
256+ escapedArgs [ 0 ] = 'ulimit -c 0 && ' + escapedArgs [ 0 ] ;
257257 }
258- testCmd += `"${ process . argv [ 0 ] } " --abort-on-uncaught-exception ` ;
259- testCmd += `"${ process . argv [ 1 ] } " child` ;
260- const child = exec ( testCmd ) ;
258+ const child = exec ( ...escapedArgs ) ;
261259 child . on ( 'exit' , function onExit ( exitCode , signal ) {
262260 const errMsg = 'Test should have aborted ' +
263261 `but instead exited with exit code ${ exitCode } ` +
@@ -888,6 +886,32 @@ function spawnPromisified(...args) {
888886 } ) ;
889887}
890888
889+ /**
890+ * Escape values in a string template literal. On Windows, this function
891+ * does not escape anything (which is fine for paths, as `"` is not a valid char
892+ * in a path on Windows), so you should use it only to escape paths – or other
893+ * values on tests which are skipped on Windows.
894+ * This function is meant to be used for tagged template strings.
895+ * @returns {[string, object | undefined] } An array that can be passed as
896+ * arguments to `exec` or `execSync`.
897+ */
898+ function escapePOSIXShell ( cmdParts , ...args ) {
899+ if ( common . isWindows ) {
900+ // On Windows, paths cannot contain `"`, so we can return the string unchanged.
901+ return [ String . raw ( { raw : cmdParts } , ...args ) ] ;
902+ }
903+ // On POSIX shells, we can pass values via the env, as there's a standard way for referencing a variable.
904+ const env = { ...process . env } ;
905+ let cmd = cmdParts [ 0 ] ;
906+ for ( let i = 0 ; i < args . length ; i ++ ) {
907+ const envVarName = `ESCAPED_${ i } ` ;
908+ env [ envVarName ] = args [ i ] ;
909+ cmd += '${' + envVarName + '}' + cmdParts [ i + 1 ] ;
910+ }
911+
912+ return [ cmd , { env } ] ;
913+ } ;
914+
891915function getPrintedStackTrace ( stderr ) {
892916 const lines = stderr . split ( '\n' ) ;
893917
@@ -951,6 +975,7 @@ const common = {
951975 childShouldThrowAndAbort,
952976 createZeroFilledFile,
953977 defaultAutoSelectFamilyAttemptTimeout,
978+ escapePOSIXShell,
954979 expectsError,
955980 expectRequiredModule,
956981 expectWarning,
0 commit comments