@@ -251,7 +251,9 @@ function file(options, callback) {
251
251
/* istanbul ignore else */
252
252
if ( err ) return cb ( err ) ;
253
253
254
+ // FIXME overall handling of opts.discardDescriptor is off
254
255
if ( opts . discardDescriptor ) {
256
+ // FIXME must not unlink
255
257
return fs . close ( fd , function _discardCallback ( err ) {
256
258
/* istanbul ignore else */
257
259
if ( err ) {
@@ -270,12 +272,11 @@ function file(options, callback) {
270
272
}
271
273
cb ( null , name , undefined , _prepareTmpFileRemoveCallback ( name , - 1 , opts ) ) ;
272
274
} ) ;
275
+ } else {
276
+ // FIXME detachDescriptor passes the descriptor whereas discardDescriptor closes it
277
+ const discardOrDetachDescriptor = opts . discardDescriptor || opts . detachDescriptor ;
278
+ cb ( null , name , fd , _prepareTmpFileRemoveCallback ( name , discardOrDetachDescriptor ? - 1 : fd , opts , false ) ) ;
273
279
}
274
- /* istanbul ignore else */
275
- if ( opts . detachDescriptor ) {
276
- return cb ( null , name , fd , _prepareTmpFileRemoveCallback ( name , - 1 , opts ) ) ;
277
- }
278
- cb ( null , name , fd , _prepareTmpFileRemoveCallback ( name , fd , opts ) ) ;
279
280
} ) ;
280
281
} ) ;
281
282
}
@@ -304,7 +305,7 @@ function fileSync(options) {
304
305
return {
305
306
name : name ,
306
307
fd : fd ,
307
- removeCallback : _prepareTmpFileRemoveCallback ( name , discardOrDetachDescriptor ? - 1 : fd , opts )
308
+ removeCallback : _prepareTmpFileRemoveCallback ( name , discardOrDetachDescriptor ? - 1 : fd , opts , true )
308
309
} ;
309
310
}
310
311
@@ -330,7 +331,7 @@ function dir(options, callback) {
330
331
/* istanbul ignore else */
331
332
if ( err ) return cb ( err ) ;
332
333
333
- cb ( null , name , _prepareTmpDirRemoveCallback ( name , opts ) ) ;
334
+ cb ( null , name , _prepareTmpDirRemoveCallback ( name , opts , false ) ) ;
334
335
} ) ;
335
336
} ) ;
336
337
}
@@ -352,7 +353,7 @@ function dirSync(options) {
352
353
353
354
return {
354
355
name : name ,
355
- removeCallback : _prepareTmpDirRemoveCallback ( name , opts )
356
+ removeCallback : _prepareTmpDirRemoveCallback ( name , opts , true )
356
357
} ;
357
358
}
358
359
@@ -370,7 +371,7 @@ function _removeFileAsync(fdPath, next) {
370
371
return next ( err ) ;
371
372
}
372
373
next ( ) ;
373
- }
374
+ } ;
374
375
375
376
if ( 0 <= fdPath [ 0 ] )
376
377
fs . close ( fdPath [ 0 ] , function ( err ) {
@@ -405,19 +406,23 @@ function _removeFileSync(fdPath) {
405
406
/**
406
407
* Prepares the callback for removal of the temporary file.
407
408
*
409
+ * Returns either a sync callback or a async callback depending on whether
410
+ * fileSync or file was called, which is expressed by the sync parameter.
411
+ *
408
412
* @param {string } name the path of the file
409
413
* @param {number } fd file descriptor
410
414
* @param {Object } opts
411
- * @returns {fileCallback }
415
+ * @param {boolean } sync
416
+ * @returns {fileCallback | fileCallbackSync }
412
417
* @private
413
418
*/
414
- function _prepareTmpFileRemoveCallback ( name , fd , opts ) {
415
- const removeCallbackSync = _prepareRemoveCallback ( _removeFileSync , [ fd , name ] ) ;
416
- const removeCallback = _prepareRemoveCallback ( _removeFileAsync , [ fd , name ] , removeCallbackSync ) ;
419
+ function _prepareTmpFileRemoveCallback ( name , fd , opts , sync ) {
420
+ const removeCallbackSync = _prepareRemoveCallback ( _removeFileSync , [ fd , name ] , sync ) ;
421
+ const removeCallback = _prepareRemoveCallback ( _removeFileAsync , [ fd , name ] , sync , removeCallbackSync ) ;
417
422
418
423
if ( ! opts . keep ) _removeObjects . unshift ( removeCallbackSync ) ;
419
424
420
- return removeCallback ;
425
+ return sync ? removeCallbackSync : removeCallback ;
421
426
}
422
427
423
428
/**
@@ -445,67 +450,62 @@ function _rimrafRemoveDirSyncWrapper(dirPath, next) {
445
450
}
446
451
}
447
452
448
- const FN_RMDIR_SYNC = fs . rmdirSync . bind ( fs ) ;
449
-
450
453
/**
451
454
* Prepares the callback for removal of the temporary directory.
452
455
*
456
+ * Returns either a sync callback or a async callback depending on whether
457
+ * tmpFileSync or tmpFile was called, which is expressed by the sync parameter.
458
+ *
453
459
* @param {string } name
454
460
* @param {Object } opts
461
+ * @param {boolean } sync
455
462
* @returns {Function } the callback
456
463
* @private
457
464
*/
458
- function _prepareTmpDirRemoveCallback ( name , opts ) {
465
+ function _prepareTmpDirRemoveCallback ( name , opts , sync ) {
459
466
const removeFunction = opts . unsafeCleanup ? _rimrafRemoveDirWrapper : fs . rmdir . bind ( fs ) ;
460
- const removeFunctionSync = opts . unsafeCleanup ? _rimrafRemoveDirSyncWrapper : FN_RMDIR_SYNC ;
461
- const removeCallbackSync = _prepareRemoveCallback ( removeFunctionSync , name ) ;
462
- const removeCallback = _prepareRemoveCallback ( removeFunction , name , removeCallbackSync ) ;
467
+ const removeFunctionSync = opts . unsafeCleanup ? _rimrafRemoveDirSyncWrapper : fs . rmdirSync . bind ( fs ) ;
468
+ const removeCallbackSync = _prepareRemoveCallback ( removeFunctionSync , name , sync ) ;
469
+ const removeCallback = _prepareRemoveCallback ( removeFunction , name , sync , removeCallbackSync ) ;
463
470
if ( ! opts . keep ) _removeObjects . unshift ( removeCallbackSync ) ;
464
471
465
- return removeCallback ;
472
+ return sync ? removeCallbackSync : removeCallback ;
466
473
}
467
474
468
475
/**
469
476
* Creates a guarded function wrapping the removeFunction call.
470
477
*
478
+ * The cleanup callback is save to be called multiple times.
479
+ * Subsequent invocations will be ignored.
480
+ *
471
481
* @param {Function } removeFunction
472
- * @param {Object } arg
473
- * @returns {Function }
482
+ * @param {string } fileOrDirName
483
+ * @param {boolean } sync
484
+ * @param {cleanupCallbackSync? } cleanupCallbackSync
485
+ * @returns {cleanupCallback | cleanupCallbackSync }
474
486
* @private
475
487
*/
476
- function _prepareRemoveCallback ( removeFunction , arg , cleanupCallbackSync ) {
488
+ function _prepareRemoveCallback ( removeFunction , fileOrDirName , sync , cleanupCallbackSync ) {
477
489
var called = false ;
478
490
491
+ // if sync is true, the next parameter will be ignored
479
492
return function _cleanupCallback ( next ) {
480
- next = next || function ( ) { } ;
493
+
494
+ /* istanbul ignore else */
481
495
if ( ! called ) {
496
+ // remove cleanupCallback from cache
482
497
const toRemove = cleanupCallbackSync || _cleanupCallback ;
483
498
const index = _removeObjects . indexOf ( toRemove ) ;
484
499
/* istanbul ignore else */
485
500
if ( index >= 0 ) _removeObjects . splice ( index , 1 ) ;
486
501
487
502
called = true ;
488
- // sync?
489
- if ( removeFunction . length === 1 ) {
490
- try {
491
- removeFunction ( arg ) ;
492
- return next ( null ) ;
493
- }
494
- catch ( err ) {
495
- // if no next is provided and since we are
496
- // in silent cleanup mode on process exit,
497
- // we will ignore the error
498
- return next ( err ) ;
499
- }
503
+ if ( sync ) {
504
+ return removeFunction ( fileOrDirName ) ;
500
505
} else {
501
- // must no call rmdirSync/rmSync this way
502
- if ( removeFunction == FN_RMDIR_SYNC ) {
503
- return removeFunction ( arg ) ;
504
- } else {
505
- return removeFunction ( arg , next ) ;
506
- }
506
+ return removeFunction ( fileOrDirName , next || function ( ) { } ) ;
507
507
}
508
- } else return next ( new Error ( 'cleanup callback has already been called' ) ) ;
508
+ }
509
509
} ;
510
510
}
511
511
@@ -726,18 +726,39 @@ _safely_install_sigint_listener();
726
726
* @param {cleanupCallback } fn the cleanup callback function
727
727
*/
728
728
729
+ /**
730
+ * @callback fileCallbackSync
731
+ * @param {?Error } err the error object if anything goes wrong
732
+ * @param {string } name the temporary file name
733
+ * @param {number } fd the file descriptor
734
+ * @param {cleanupCallbackSync } fn the cleanup callback function
735
+ */
736
+
729
737
/**
730
738
* @callback dirCallback
731
739
* @param {?Error } err the error object if anything goes wrong
732
740
* @param {string } name the temporary file name
733
741
* @param {cleanupCallback } fn the cleanup callback function
734
742
*/
735
743
744
+ /**
745
+ * @callback dirCallbackSync
746
+ * @param {?Error } err the error object if anything goes wrong
747
+ * @param {string } name the temporary file name
748
+ * @param {cleanupCallbackSync } fn the cleanup callback function
749
+ */
750
+
736
751
/**
737
752
* Removes the temporary created file or directory.
738
753
*
739
754
* @callback cleanupCallback
740
- * @param {simpleCallback } [next] function to call after entry was removed
755
+ * @param {simpleCallback } [next] function to call whenever the tmp object needs to be removed
756
+ */
757
+
758
+ /**
759
+ * Removes the temporary created file or directory.
760
+ *
761
+ * @callback cleanupCallbackSync
741
762
*/
742
763
743
764
/**
0 commit comments