@@ -120,29 +120,29 @@ function close(stream, err, cb) {
120120}
121121
122122function importFd ( stream , options ) {
123- stream . fd = null ;
124- if ( options . fd != null ) {
125- if ( typeof options . fd === 'number' ) {
126- // When fd is a raw descriptor, we must keep our fingers crossed
127- // that the descriptor won't get closed, or worse, replaced with
128- // another one
129- // https://github.com/nodejs/node/issues/35862
130- stream . fd = options . fd ;
131- } else if ( typeof options . fd === 'object' &&
132- options . fd instanceof FileHandle ) {
133- // When fd is a FileHandle we can listen for 'close' events
134- if ( options . fs )
135- // FileHandle is not supported with custom fs operations
136- throw new ERR_METHOD_NOT_IMPLEMENTED ( 'FileHandle with fs' ) ;
137- stream [ kHandle ] = options . fd ;
138- stream . fd = options . fd . fd ;
139- stream [ kFs ] = FileHandleOperations ( stream [ kHandle ] ) ;
140- stream [ kHandle ] [ kRef ] ( ) ;
141- options . fd . on ( 'close' , FunctionPrototypeBind ( stream . close , stream ) ) ;
142- } else
143- throw ERR_INVALID_ARG_TYPE ( 'options.fd' ,
144- [ 'number' , 'FileHandle' ] , options . fd ) ;
123+ if ( typeof options . fd === 'number' ) {
124+ // When fd is a raw descriptor, we must keep our fingers crossed
125+ // that the descriptor won't get closed, or worse, replaced with
126+ // another one
127+ // https://github.com/nodejs/node/issues/35862
128+ stream [ kFs ] = options . fs || fs ;
129+ return options . fd ;
130+ } else if ( typeof options . fd === 'object' &&
131+ options . fd instanceof FileHandle ) {
132+ // When fd is a FileHandle we can listen for 'close' events
133+ if ( options . fs ) {
134+ // FileHandle is not supported with custom fs operations
135+ throw new ERR_METHOD_NOT_IMPLEMENTED ( 'FileHandle with fs' ) ;
136+ }
137+ stream [ kHandle ] = options . fd ;
138+ stream [ kFs ] = FileHandleOperations ( stream [ kHandle ] ) ;
139+ stream [ kHandle ] [ kRef ] ( ) ;
140+ options . fd . on ( 'close' , FunctionPrototypeBind ( stream . close , stream ) ) ;
141+ return options . fd . fd ;
145142 }
143+
144+ throw ERR_INVALID_ARG_TYPE ( 'options.fd' ,
145+ [ 'number' , 'FileHandle' ] , options . fd ) ;
146146}
147147
148148function ReadStream ( path , options ) {
@@ -158,21 +158,29 @@ function ReadStream(path, options) {
158158 options . autoDestroy = false ;
159159 }
160160
161- this [ kFs ] = options . fs || fs ;
161+ if ( options . fd == null ) {
162+ this . fd = null ;
163+ this [ kFs ] = options . fs || fs ;
164+ validateFunction ( this [ kFs ] . open , 'options.fs.open' ) ;
162165
163- validateFunction ( this [ kFs ] . open , 'options.fs.open' ) ;
164- validateFunction ( this [ kFs ] . read , 'options.fs.read' ) ;
165- validateFunction ( this [ kFs ] . close , 'options.fs.close' ) ;
166+ // Path will be ignored when fd is specified, so it can be falsy
167+ this . path = toPathIfFileURL ( path ) ;
168+ this . flags = options . flags === undefined ? 'r' : options . flags ;
169+ this . mode = options . mode === undefined ? 0o666 : options . mode ;
170+
171+ validatePath ( this . path ) ;
172+ } else {
173+ this . fd = getValidatedFd ( importFd ( this , options ) ) ;
174+ }
166175
167176 options . autoDestroy = options . autoClose === undefined ?
168177 true : options . autoClose ;
169178
170- // Path will be ignored when fd is specified, so it can be falsy
171- this . path = toPathIfFileURL ( path ) ;
172- this . flags = options . flags === undefined ? 'r' : options . flags ;
173- this . mode = options . mode === undefined ? 0o666 : options . mode ;
179+ validateFunction ( this [ kFs ] . read , 'options.fs.read' ) ;
174180
175- importFd ( this , options ) ;
181+ if ( options . autoDestroy ) {
182+ validateFunction ( this [ kFs ] . close , 'options.fs.close' ) ;
183+ }
176184
177185 this . start = options . start ;
178186 this . end = options . end ;
@@ -187,12 +195,6 @@ function ReadStream(path, options) {
187195 this . pos = this . start ;
188196 }
189197
190- // If fd has been set, validate, otherwise validate path.
191- if ( this . fd != null ) {
192- this . fd = getValidatedFd ( this . fd ) ;
193- } else {
194- validatePath ( this . path ) ;
195- }
196198
197199 if ( this . end === undefined ) {
198200 this . end = Infinity ;
@@ -310,9 +312,23 @@ function WriteStream(path, options) {
310312 // Only buffers are supported.
311313 options . decodeStrings = true ;
312314
313- this [ kFs ] = options . fs || fs ;
315+ if ( options . fd == null ) {
316+ this . fd = null ;
317+ this [ kFs ] = options . fs || fs ;
318+ validateFunction ( this [ kFs ] . open , 'options.fs.open' ) ;
319+
320+ // Path will be ignored when fd is specified, so it can be falsy
321+ this . path = toPathIfFileURL ( path ) ;
322+ this . flags = options . flags === undefined ? 'w' : options . flags ;
323+ this . mode = options . mode === undefined ? 0o666 : options . mode ;
324+
325+ validatePath ( this . path ) ;
326+ } else {
327+ this . fd = getValidatedFd ( importFd ( this , options ) ) ;
328+ }
314329
315- validateFunction ( this [ kFs ] . open , 'options.fs.open' ) ;
330+ options . autoDestroy = options . autoClose === undefined ?
331+ true : options . autoClose ;
316332
317333 if ( ! this [ kFs ] . write && ! this [ kFs ] . writev ) {
318334 throw new ERR_INVALID_ARG_TYPE ( 'options.fs.write' , 'function' ,
@@ -327,7 +343,9 @@ function WriteStream(path, options) {
327343 validateFunction ( this [ kFs ] . writev , 'options.fs.writev' ) ;
328344 }
329345
330- validateFunction ( this [ kFs ] . close , 'options.fs.close' ) ;
346+ if ( options . autoDestroy ) {
347+ validateFunction ( this [ kFs ] . close , 'options.fs.close' ) ;
348+ }
331349
332350 // It's enough to override either, in which case only one will be used.
333351 if ( ! this [ kFs ] . write ) {
@@ -337,28 +355,12 @@ function WriteStream(path, options) {
337355 this . _writev = null ;
338356 }
339357
340- options . autoDestroy = options . autoClose === undefined ?
341- true : options . autoClose ;
342-
343- // Path will be ignored when fd is specified, so it can be falsy
344- this . path = toPathIfFileURL ( path ) ;
345- this . flags = options . flags === undefined ? 'w' : options . flags ;
346- this . mode = options . mode === undefined ? 0o666 : options . mode ;
347-
348- importFd ( this , options ) ;
349-
350358 this . start = options . start ;
351359 this . pos = undefined ;
352360 this . bytesWritten = 0 ;
353361 this . closed = false ;
354362 this [ kIsPerformingIO ] = false ;
355363
356- // If fd has been set, validate, otherwise validate path.
357- if ( this . fd != null ) {
358- this . fd = getValidatedFd ( this . fd ) ;
359- } else {
360- validatePath ( this . path ) ;
361- }
362364
363365 if ( this . start !== undefined ) {
364366 validateInteger ( this . start , 'start' , 0 ) ;
0 commit comments