@@ -373,3 +373,111 @@ exports.clearImmediate = function(immediate) {
373
373
process . _needImmediateCallback = false ;
374
374
}
375
375
} ;
376
+
377
+
378
+ // Internal APIs that need timeouts should use timers._unrefActive isntead of
379
+ // timers.active as internal timeouts shouldn't hold the loop open
380
+
381
+ var unrefList , unrefTimer ;
382
+
383
+
384
+ function unrefTimeout ( ) {
385
+ var now = Date . now ( ) ;
386
+
387
+ debug ( 'unrefTimer fired' ) ;
388
+
389
+ var first ;
390
+ while ( first = L . peek ( unrefList ) ) {
391
+ var diff = now - first . _idleStart ;
392
+
393
+ if ( diff < first . _idleTimeout ) {
394
+ diff = first . _idleTimeout - diff ;
395
+ unrefTimer . start ( diff , 0 ) ;
396
+ unrefTimer . when = now + diff ;
397
+ debug ( 'unrefTimer rescheudling for later' ) ;
398
+ return ;
399
+ }
400
+
401
+ L . remove ( first ) ;
402
+
403
+ var domain = first . domain ;
404
+
405
+ if ( ! first . _onTimeout ) continue ;
406
+ if ( domain && domain . _disposed ) continue ;
407
+
408
+ try {
409
+ if ( domain ) domain . enter ( ) ;
410
+ var threw = true ;
411
+ debug ( 'unreftimer firing timeout' ) ;
412
+ first . _onTimeout ( ) ;
413
+ threw = false ;
414
+ if ( domain ) domain . exit ( ) ;
415
+ } finally {
416
+ if ( threw ) process . nextTick ( unrefTimeout ) ;
417
+ }
418
+ }
419
+
420
+ debug ( 'unrefList is empty' ) ;
421
+ unrefTimer . when = - 1 ;
422
+ }
423
+
424
+
425
+ exports . _unrefActive = function ( item ) {
426
+ var msecs = item . _idleTimeout ;
427
+ if ( ! msecs || msecs < 0 ) return ;
428
+ assert ( msecs >= 0 ) ;
429
+
430
+ L . remove ( item ) ;
431
+
432
+ if ( ! unrefList ) {
433
+ debug ( 'unrefList initialized' ) ;
434
+ unrefList = { } ;
435
+ L . init ( unrefList ) ;
436
+
437
+ debug ( 'unrefTimer initialized' ) ;
438
+ unrefTimer = new Timer ( ) ;
439
+ unrefTimer . unref ( ) ;
440
+ unrefTimer . when = - 1 ;
441
+ unrefTimer . ontimeout = unrefTimeout ;
442
+ }
443
+
444
+ var now = Date . now ( ) ;
445
+ item . _idleStart = now ;
446
+
447
+ if ( L . isEmpty ( unrefList ) ) {
448
+ debug ( 'unrefList empty' ) ;
449
+ L . append ( unrefList , item ) ;
450
+
451
+ unrefTimer . start ( msecs , 0 ) ;
452
+ unrefTimer . when = now + msecs ;
453
+ debug ( 'unrefTimer scheduled' ) ;
454
+ return ;
455
+ }
456
+
457
+ var when = now + msecs ;
458
+
459
+ debug ( 'unrefList find where we can insert' ) ;
460
+
461
+ var cur , them ;
462
+
463
+ for ( cur = unrefList . _idlePrev ; cur != unrefList ; cur = cur . _idlePrev ) {
464
+ them = cur . _idleStart + cur . _idleTimeout ;
465
+
466
+ if ( when < them ) {
467
+ debug ( 'unrefList inserting into middle of list' ) ;
468
+
469
+ L . append ( cur , item ) ;
470
+
471
+ if ( unrefTimer . when > when ) {
472
+ debug ( 'unrefTimer is scheduled to fire too late, reschedule' ) ;
473
+ unrefTimer . start ( msecs , 0 ) ;
474
+ unrefTimer . when = when ;
475
+ }
476
+
477
+ return ;
478
+ }
479
+ }
480
+
481
+ debug ( 'unrefList append to end' ) ;
482
+ L . append ( unrefList , item ) ;
483
+ } ;
0 commit comments