22/* eslint max-len: 0 */
33
44import execa from 'execa' ;
5+ import { sh } from 'puka' ;
56import makeTemp from './_temp.js' ;
67import * as fs from '../src/util/fs.js' ;
7- import * as misc from '../src/util/misc.js' ;
88import * as constants from '../src/constants.js' ;
99import { explodeLockfile } from './commands/_helpers.js' ;
1010
@@ -77,7 +77,7 @@ async function runYarn(args: Array<string> = [], options: Object = {}): Promise<
7777 options [ 'extendEnv' ] = false ;
7878 }
7979 options [ 'env' ] [ 'FORCE_COLOR' ] = 0 ;
80- const { stdout, stderr} = await execa ( path . resolve ( __dirname , '../bin/yarn' ) , args , options ) ;
80+ const { stdout, stderr} = await execa . shell ( sh ` ${ path . resolve ( __dirname , '../bin/yarn' ) } ${ args } ` , options ) ;
8181
8282 return [ stdout , stderr ] ;
8383}
@@ -260,9 +260,8 @@ test('yarnrc binary path (executable)', async () => {
260260 expect ( stdoutOutput . toString ( ) . trim ( ) ) . toEqual ( 'override called' ) ;
261261} ) ;
262262
263- // Windows could run these tests, but we currently suffer from an escaping issue that breaks them (#4135)
264- if ( process . platform !== 'win32' ) {
265- test ( 'yarn run <script> --opt' , async ( ) => {
263+ for ( const withDoubleDash of [ false , true ] ) {
264+ test ( `yarn run <script> ${ withDoubleDash ? '-- ' : '' } --opt` , async ( ) => {
266265 const cwd = await makeTemp ( ) ;
267266
268267 await fs . writeFile (
@@ -272,48 +271,37 @@ if (process.platform !== 'win32') {
272271 } ) ,
273272 ) ;
274273
275- const command = path . resolve ( __dirname , '../bin/yarn' ) ;
276274 const options = { cwd, env : { YARN_SILENT : 1 } } ;
277275
278- const { stderr : stderr , stdout : stdout } = execa ( command , [ 'run' , 'echo' , '--opt' ] , options ) ;
279-
280- const stdoutPromise = misc . consumeStream ( stdout ) ;
281- const stderrPromise = misc . consumeStream ( stderr ) ;
282-
283- const [ stdoutOutput , stderrOutput ] = await Promise . all ( [ stdoutPromise , stderrPromise ] ) ;
276+ const [ stdoutOutput , stderrOutput ] = await runYarn (
277+ [ 'run' , 'echo' , ...( withDoubleDash ? [ '--' ] : [ ] ) , '--opt' ] ,
278+ options ,
279+ ) ;
284280
285281 expect ( stdoutOutput . toString ( ) . trim ( ) ) . toEqual ( '--opt' ) ;
286- expect ( stderrOutput . toString ( ) ) . not . toMatch (
282+ ( exp => ( withDoubleDash ? exp : exp . not ) ) ( expect ( stderrOutput . toString ( ) ) ) . toMatch (
287283 / F r o m Y a r n 1 \. 0 o n w a r d s , s c r i p t s d o n ' t r e q u i r e " - - " f o r o p t i o n s t o b e f o r w a r d e d / ,
288284 ) ;
289285 } ) ;
286+ }
290287
291- test ( 'yarn run <script> -- --opt' , async ( ) => {
292- const cwd = await makeTemp ( ) ;
293-
294- await fs . writeFile (
295- path . join ( cwd , 'package.json' ) ,
296- JSON . stringify ( {
297- scripts : { echo : `echo` } ,
298- } ) ,
299- ) ;
300-
301- const command = path . resolve ( __dirname , '../bin/yarn' ) ;
302- const options = { cwd, env : { YARN_SILENT : 1 } } ;
288+ test ( 'yarn run <script> <strings that need escaping>' , async ( ) => {
289+ const cwd = await makeTemp ( ) ;
303290
304- const { stderr : stderr , stdout : stdout } = execa ( command , [ 'run' , 'echo' , '--' , '--opt' ] , options ) ;
291+ await fs . writeFile (
292+ path . join ( cwd , 'package.json' ) ,
293+ JSON . stringify ( {
294+ scripts : { stringify : `node -p "JSON.stringify(process.argv.slice(1))"` } ,
295+ } ) ,
296+ ) ;
305297
306- const stdoutPromise = misc . consumeStream ( stdout ) ;
307- const stderrPromise = misc . consumeStream ( stderr ) ;
298+ const options = { cwd, env : { YARN_SILENT : 1 } } ;
308299
309- const [ stdoutOutput , stderrOutput ] = await Promise . all ( [ stdoutPromise , stderrPromise ] ) ;
300+ const trickyStrings = [ '$PWD' , '%CD%' , '^' , '!' , '\\' , '>' , '<' , '|' , '&' , "'" , '"' , '`' , ' ' ] ;
301+ const [ stdout ] = await runYarn ( [ 'stringify' , ...trickyStrings ] , options ) ;
310302
311- expect ( stdoutOutput . toString ( ) . trim ( ) ) . toEqual ( '--opt' ) ;
312- expect ( stderrOutput . toString ( ) ) . toMatch (
313- / F r o m Y a r n 1 \. 0 o n w a r d s , s c r i p t s d o n ' t r e q u i r e " - - " f o r o p t i o n s t o b e f o r w a r d e d / ,
314- ) ;
315- } ) ;
316- }
303+ expect ( stdout . toString ( ) . trim ( ) ) . toEqual ( JSON . stringify ( trickyStrings ) ) ;
304+ } ) ;
317305
318306test ( 'cache folder fallback' , async ( ) => {
319307 const cwd = await makeTemp ( ) ;
0 commit comments