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