1
- var EventEmitter = require ( 'events' )
2
- var spawn = require ( 'child_process' ) . spawn
3
- var stream = require ( 'stream' )
1
+ const EventEmitter = require ( 'events' )
2
+ const spawn = require ( 'child_process' ) . spawn
3
+ const stream = require ( 'stream' )
4
4
5
- var Duplex = stream . Duplex
6
- var Writable = stream . Writable
5
+ const Duplex = stream . Duplex
6
+ const Readable = stream . Readable
7
+ const Writable = stream . Writable
7
8
8
9
9
10
function noop ( ) { }
@@ -25,19 +26,19 @@ function wrapStdio(command, argv, options)
25
26
var stderr = stdio [ 2 ]
26
27
27
28
// Wrap stdio
28
- if ( typeof stdin === 'string'
29
+ if ( typeof stdin === 'string' || typeof stdin === 'number'
29
30
|| stdin && stdin . constructor . name === 'ReadStream' )
30
31
stdin = null
31
32
else
32
33
stdio [ 0 ] = 'pipe'
33
34
34
- if ( typeof stdout === 'string'
35
+ if ( typeof stdout === 'string' || typeof stdout === 'number'
35
36
|| stdout && stdout . constructor . name === 'WriteStream' )
36
37
stdout = null
37
38
else
38
39
stdio [ 1 ] = 'pipe'
39
40
40
- if ( typeof stderr === 'string'
41
+ if ( typeof stderr === 'string' || typeof stderr === 'number'
41
42
|| stderr && stderr . constructor . name === 'WriteStream' )
42
43
stderr = null
43
44
else
@@ -47,17 +48,17 @@ function wrapStdio(command, argv, options)
47
48
var cp = spawn ( command , argv , options )
48
49
49
50
// Adjust events, pipe streams and restore stdio
50
- if ( stdin )
51
+ if ( stdin != null )
51
52
{
52
53
stdin . pipe ( cp . stdin )
53
54
cp . stdin = null
54
55
}
55
- if ( stdout )
56
+ if ( stdout != null )
56
57
{
57
58
cp . stdout . pipe ( stdout )
58
59
cp . stdout = null
59
60
}
60
- if ( stderr )
61
+ if ( stderr != null )
61
62
{
62
63
cp . stderr . pipe ( stderr )
63
64
cp . stderr = null
@@ -83,47 +84,44 @@ function spawnStream(command, argv, options)
83
84
var stdout = stdio [ 1 ]
84
85
var stderr = stdio [ 2 ]
85
86
86
- if ( stdin == null ) stdin = 'pipe'
87
- if ( stdout == null ) stdout = 'pipe'
88
- if ( stderr == null ) stderr = 'pipe'
89
-
90
87
var cp = wrapStdio ( command , argv , options )
91
88
92
- stdin = ( stdin === 'pipe' ) ? cp . stdin : null
93
- stdout = ( stdout === 'pipe' ) ? cp . stdout : null
94
- stderr = ( stderr === 'pipe' ) ? cp . stderr : null
89
+ stdin = ( stdin == null || stdin == = 'pipe' ) ? cp . stdin : null
90
+ stdout = ( stdout == null || stdout == = 'pipe' ) ? cp . stdout : null
91
+ stderr = ( stderr == null || stderr == = 'pipe' ) ? cp . stderr : null
95
92
96
93
var result
97
94
98
- // Both `stdin` and `stdout` are open, probably the normal case.
99
- // Create a `Duplex` object with them so command can be used as a filter.
100
- if ( stdin && stdout )
101
- {
102
- result = Duplex ( )
103
- result . _read = noop
104
- result . _write = stdin . write . bind ( stdin )
95
+ // Both `stdin` and `stdout` are open, probably the normal case. Create a
96
+ // `Duplex` object with them so command can be used as a filter
97
+ if ( stdin && stdout ) result = Duplex ( )
105
98
106
- result . on ( 'finish' , stdin . end . bind ( stdin ) )
99
+ // Only `stdout` is open, use it directly
100
+ else if ( stdout ) result = Readable ( )
107
101
108
- stdout
109
- . on ( 'data' , result . push . bind ( result ) )
110
- . on ( 'end' , result . emit . bind ( result , 'end' ) )
111
- }
102
+ // Only `stdin` is open, ensure is always 'only' `Writable`
103
+ else if ( stdin ) result = Writable ( )
104
+
105
+ // Both `stdin` and `stdout` are clossed
106
+ else result = new EventEmitter ( )
112
107
113
- // Only `stdin` is open, ensure is always 'only' writable.
114
- else if ( stdin )
108
+ // Connect stdio streams
109
+ if ( stdin )
115
110
{
116
- result = Writable ( )
117
111
result . _write = stdin . write . bind ( stdin )
118
-
119
- result . on ( 'finish' , stdin . end . bind ( stdin ) )
112
+ result . once ( 'finish' , stdin . end . bind ( stdin ) )
120
113
}
121
114
122
- // Only `stdout` is open, use it directly.
123
- else if ( stdout ) result = stdout
115
+ if ( stdout )
116
+ {
117
+ result . _read = noop
118
+ stdout . on ( 'data' , result . push . bind ( result ) )
119
+ stdout . once ( 'end' , result . push . bind ( result , null ) )
120
+ }
124
121
125
- // Both `stdin` and `stdout` are clossed.
126
- else result = new EventEmitter ( )
122
+ // Use child process `exit` event instead of missing `stdout` `end` event
123
+ else
124
+ cp . once ( 'exit' , result . emit . bind ( result , 'end' ) )
127
125
128
126
if ( stderr )
129
127
{
@@ -138,12 +136,10 @@ function spawnStream(command, argv, options)
138
136
if ( out_stderr ) out_stderr . pipe ( stderr )
139
137
}
140
138
139
+ // Propagate process events
141
140
cp . on ( 'error' , result . emit . bind ( result , 'error' ) )
142
141
cp . on ( 'exit' , result . emit . bind ( result , 'exit' ) )
143
142
144
- // No `stdout`, emit `end` event when child process exit
145
- if ( ! stdout ) cp . once ( 'exit' , result . emit . bind ( result , 'end' ) )
146
-
147
143
return result
148
144
}
149
145
0 commit comments