11'use strict' ; 
22
3- // This value is used to prevent the nextTickQueue from becoming too 
4- // large and cause the process to run out of memory. When this value 
5- // is reached the nextTimeQueue array will be shortened (see tickDone 
6- // for details). 
7- const  kMaxCallbacksPerLoop  =  1e4 ; 
8- 
93exports . setup  =  setupNextTick ; 
104// Will be overwritten when setupNextTick() is called. 
115exports . nextTick  =  null ; 
126
13- class  NextTickQueue  { 
14-   constructor ( )  { 
15-     this . head  =  null ; 
16-     this . tail  =  null ; 
17-   } 
18- 
19-   push ( v )  { 
20-     const  entry  =  {  data : v ,  next : null  } ; 
21-     if  ( this . tail  !==  null ) 
22-       this . tail . next  =  entry ; 
23-     else 
24-       this . head  =  entry ; 
25-     this . tail  =  entry ; 
26-   } 
27- 
28-   shift ( )  { 
29-     if  ( this . head  ===  null ) 
30-       return ; 
31-     const  ret  =  this . head . data ; 
32-     if  ( this . head  ===  this . tail ) 
33-       this . head  =  this . tail  =  null ; 
34-     else 
35-       this . head  =  this . head . next ; 
36-     return  ret ; 
37-   } 
38- 
39-   clear ( )  { 
40-     this . head  =  null ; 
41-     this . tail  =  null ; 
42-   } 
43- } 
44- 
457function  setupNextTick ( )  { 
468  const  async_wrap  =  process . binding ( 'async_wrap' ) ; 
479  const  async_hooks  =  require ( 'internal/async_hooks' ) ; 
@@ -56,15 +18,47 @@ function setupNextTick() {
5618  // Grab the constants necessary for working with internal arrays. 
5719  const  {  kInit,  kDestroy,  kAsyncIdCounter }  =  async_wrap . constants ; 
5820  const  {  async_id_symbol,  trigger_async_id_symbol }  =  async_wrap ; 
59-   const  nextTickQueue  =  new  NextTickQueue ( ) ; 
60-   var  microtasksScheduled  =  false ; 
6121
62-   // Used to run V8's micro task queue. 
63-   var  _runMicrotasks  =  { } ; 
22+   // tickInfo is used so that the C++ code in src/node.cc can 
23+   // have easy access to our nextTick state, and avoid unnecessary 
24+   // calls into JS land. 
25+   // runMicrotasks is used to run V8's micro task queue. 
26+   const  [ 
27+     tickInfo , 
28+     runMicrotasks 
29+   ]  =  process . _setupNextTick ( _tickCallback ) ; 
6430
6531  // *Must* match Environment::TickInfo::Fields in src/env.h. 
66-   var  kIndex  =  0 ; 
67-   var  kLength  =  1 ; 
32+   const  kScheduled  =  0 ; 
33+ 
34+   const  nextTickQueue  =  { 
35+     head : null , 
36+     tail : null , 
37+     push ( data )  { 
38+       const  entry  =  {  data,  next : null  } ; 
39+       if  ( this . tail  !==  null )  { 
40+         this . tail . next  =  entry ; 
41+       }  else  { 
42+         this . head  =  entry ; 
43+         tickInfo [ kScheduled ]  =  1 ; 
44+       } 
45+       this . tail  =  entry ; 
46+     } , 
47+     shift ( )  { 
48+       if  ( this . head  ===  null ) 
49+         return ; 
50+       const  ret  =  this . head . data ; 
51+       if  ( this . head  ===  this . tail )  { 
52+         this . head  =  this . tail  =  null ; 
53+         tickInfo [ kScheduled ]  =  0 ; 
54+       }  else  { 
55+         this . head  =  this . head . next ; 
56+       } 
57+       return  ret ; 
58+     } 
59+   } ; 
60+ 
61+   var  microtasksScheduled  =  false ; 
6862
6963  process . nextTick  =  nextTick ; 
7064  // Needs to be accessible from beyond this scope. 
@@ -73,25 +67,6 @@ function setupNextTick() {
7367  // Set the nextTick() function for internal usage. 
7468  exports . nextTick  =  internalNextTick ; 
7569
76-   // This tickInfo thing is used so that the C++ code in src/node.cc 
77-   // can have easy access to our nextTick state, and avoid unnecessary 
78-   // calls into JS land. 
79-   const  tickInfo  =  process . _setupNextTick ( _tickCallback ,  _runMicrotasks ) ; 
80- 
81-   _runMicrotasks  =  _runMicrotasks . runMicrotasks ; 
82- 
83-   function  tickDone ( )  { 
84-     if  ( tickInfo [ kLength ]  !==  0 )  { 
85-       if  ( tickInfo [ kLength ]  <=  tickInfo [ kIndex ] )  { 
86-         nextTickQueue . clear ( ) ; 
87-         tickInfo [ kLength ]  =  0 ; 
88-       }  else  { 
89-         tickInfo [ kLength ]  -=  tickInfo [ kIndex ] ; 
90-       } 
91-     } 
92-     tickInfo [ kIndex ]  =  0 ; 
93-   } 
94- 
9570  const  microTasksTickObject  =  { 
9671    callback : runMicrotasksCallback , 
9772    args : undefined , 
@@ -105,38 +80,27 @@ function setupNextTick() {
10580    // For the moment all microtasks come from the void until the PromiseHook 
10681    // API is implemented. 
10782    nextTickQueue . push ( microTasksTickObject ) ; 
108- 
109-     tickInfo [ kLength ] ++ ; 
11083    microtasksScheduled  =  true ; 
11184  } 
11285
11386  function  runMicrotasksCallback ( )  { 
11487    microtasksScheduled  =  false ; 
115-     _runMicrotasks ( ) ; 
88+     runMicrotasks ( ) ; 
11689
117-     if  ( tickInfo [ kIndex ]  <  tickInfo [ kLength ]  || 
118-         emitPendingUnhandledRejections ( ) )  { 
90+     if  ( nextTickQueue . head  !==  null  ||  emitPendingUnhandledRejections ( ) ) 
11991      scheduleMicrotasks ( ) ; 
120-     } 
12192  } 
12293
12394  function  _tickCallback ( )  { 
95+     let  tock ; 
12496    do  { 
125-       while  ( tickInfo [ kIndex ]  <  tickInfo [ kLength ] )  { 
126-         ++ tickInfo [ kIndex ] ; 
127-         const  tock  =  nextTickQueue . shift ( ) ; 
128- 
129-         // CHECK(Number.isSafeInteger(tock[async_id_symbol])) 
130-         // CHECK(tock[async_id_symbol] > 0) 
131-         // CHECK(Number.isSafeInteger(tock[trigger_async_id_symbol])) 
132-         // CHECK(tock[trigger_async_id_symbol] > 0) 
133- 
97+       while  ( tock  =  nextTickQueue . shift ( ) )  { 
13498        const  asyncId  =  tock [ async_id_symbol ] ; 
13599        emitBefore ( asyncId ,  tock [ trigger_async_id_symbol ] ) ; 
136100        // emitDestroy() places the async_id_symbol into an asynchronous queue 
137101        // that calls the destroy callback in the future. It's called before 
138102        // calling tock.callback so destroy will be called even if the callback 
139-         // throws an exception that is handles  by 'uncaughtException' or a 
103+         // throws an exception that is handled  by 'uncaughtException' or a 
140104        // domain. 
141105        // TODO(trevnorris): This is a bit of a hack. It relies on the fact 
142106        // that nextTick() doesn't allow the event loop to proceed, but if 
@@ -152,24 +116,21 @@ function setupNextTick() {
152116          Reflect . apply ( callback ,  undefined ,  tock . args ) ; 
153117
154118        emitAfter ( asyncId ) ; 
155- 
156-         if  ( kMaxCallbacksPerLoop  <  tickInfo [ kIndex ] ) 
157-           tickDone ( ) ; 
158119      } 
159-       tickDone ( ) ; 
160-       _runMicrotasks ( ) ; 
120+       runMicrotasks ( ) ; 
161121      emitPendingUnhandledRejections ( ) ; 
162-     }  while  ( tickInfo [ kLength ]  !==  0 ) ; 
122+     }  while  ( nextTickQueue . head  !==  null ) ; 
163123  } 
164124
165125  class  TickObject  { 
166-     constructor ( callback ,  args ,  asyncId ,   triggerAsyncId )  { 
126+     constructor ( callback ,  args ,  triggerAsyncId )  { 
167127      // this must be set to null first to avoid function tracking 
168128      // on the hidden class, revisit in V8 versions after 6.2 
169129      this . callback  =  null ; 
170130      this . callback  =  callback ; 
171131      this . args  =  args ; 
172132
133+       const  asyncId  =  ++ async_id_fields [ kAsyncIdCounter ] ; 
173134      this [ async_id_symbol ]  =  asyncId ; 
174135      this [ trigger_async_id_symbol ]  =  triggerAsyncId ; 
175136
@@ -203,13 +164,7 @@ function setupNextTick() {
203164          args [ i  -  1 ]  =  arguments [ i ] ; 
204165    } 
205166
206-     // In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the 
207-     // TickObject incurs a significant performance penalty in the 
208-     // next-tick-breadth-args benchmark (revisit later) 
209-     ++ tickInfo [ kLength ] ; 
210-     nextTickQueue . push ( new  TickObject ( callback , 
211-                                       args , 
212-                                       ++ async_id_fields [ kAsyncIdCounter ] , 
167+     nextTickQueue . push ( new  TickObject ( callback ,  args , 
213168                                      getDefaultTriggerAsyncId ( ) ) ) ; 
214169  } 
215170
@@ -238,13 +193,6 @@ function setupNextTick() {
238193
239194    if  ( triggerAsyncId  ===  null ) 
240195      triggerAsyncId  =  getDefaultTriggerAsyncId ( ) ; 
241-     // In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the 
242-     // TickObject incurs a significant performance penalty in the 
243-     // next-tick-breadth-args benchmark (revisit later) 
244-     ++ tickInfo [ kLength ] ; 
245-     nextTickQueue . push ( new  TickObject ( callback , 
246-                                       args , 
247-                                       ++ async_id_fields [ kAsyncIdCounter ] , 
248-                                       triggerAsyncId ) ) ; 
196+     nextTickQueue . push ( new  TickObject ( callback ,  args ,  triggerAsyncId ) ) ; 
249197  } 
250198} 
0 commit comments