@@ -41,6 +41,7 @@ const {
4141
4242const { AsyncResource } = require ( 'async_hooks' ) ;
4343
44+ let experimentalTaskOrdering ;
4445// *Must* match Environment::TickInfo::Fields in src/env.h.
4546const kHasTickScheduled = 0 ;
4647
@@ -55,16 +56,26 @@ function setHasTickScheduled(value) {
5556const queue = new FixedQueue ( ) ;
5657
5758// Should be in sync with RunNextTicksNative in node_task_queue.cc
58- function runNextTicks ( ) {
59+ function runNextTicksNew ( ) {
5960 if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
6061 runMicrotasks ( ) ;
6162 if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
6263 return ;
6364
64- processTicksAndRejections ( ) ;
65+ processTicksAndRejectionsNew ( ) ;
6566}
6667
67- function processTicksAndRejections ( ) {
68+ // Should be in sync with RunNextTicksNative in node_task_queue.cc
69+ function runNextTicksOld ( ) {
70+ if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
71+ runMicrotasks ( ) ;
72+ if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
73+ return ;
74+
75+ processTicksAndRejectionsOld ( ) ;
76+ }
77+
78+ function processTicksAndRejectionsOld ( ) {
6879 let tock ;
6980 do {
7081 while ( ( tock = queue . shift ( ) ) !== null ) {
@@ -98,6 +109,40 @@ function processTicksAndRejections() {
98109 setHasRejectionToWarn ( false ) ;
99110}
100111
112+ function processTicksAndRejectionsNew ( ) {
113+ let tock ;
114+ do {
115+ runMicrotasks ( ) ;
116+ while ( ( tock = queue . shift ( ) ) !== null ) {
117+ const asyncId = tock [ async_id_symbol ] ;
118+ emitBefore ( asyncId , tock [ trigger_async_id_symbol ] , tock ) ;
119+
120+ try {
121+ const callback = tock . callback ;
122+ if ( tock . args === undefined ) {
123+ callback ( ) ;
124+ } else {
125+ const args = tock . args ;
126+ switch ( args . length ) {
127+ case 1 : callback ( args [ 0 ] ) ; break ;
128+ case 2 : callback ( args [ 0 ] , args [ 1 ] ) ; break ;
129+ case 3 : callback ( args [ 0 ] , args [ 1 ] , args [ 2 ] ) ; break ;
130+ case 4 : callback ( args [ 0 ] , args [ 1 ] , args [ 2 ] , args [ 3 ] ) ; break ;
131+ default : callback ( ...args ) ;
132+ }
133+ }
134+ } finally {
135+ if ( destroyHooksExist ( ) )
136+ emitDestroy ( asyncId ) ;
137+ }
138+
139+ emitAfter ( asyncId ) ;
140+ }
141+ } while ( ! queue . isEmpty ( ) || processPromiseRejections ( ) ) ;
142+ setHasTickScheduled ( false ) ;
143+ setHasRejectionToWarn ( false ) ;
144+ }
145+
101146// `nextTick()` will not enqueue any callback when the process is about to
102147// exit since the callback would not have a chance to be executed.
103148function nextTick ( callback ) {
@@ -160,13 +205,23 @@ function queueMicrotask(callback) {
160205
161206module . exports = {
162207 setupTaskQueue ( ) {
208+ if ( experimentalTaskOrdering === undefined ) {
209+ const { getOptionValue } = require ( 'internal/options' ) ;
210+ experimentalTaskOrdering = getOptionValue ( '--experimental-task-ordering' ) ;
211+ }
212+
163213 // Sets the per-isolate promise rejection callback
164214 listenForRejections ( ) ;
165215 // Sets the callback to be run in every tick.
166- setTickCallback ( processTicksAndRejections ) ;
216+ setTickCallback ( experimentalTaskOrdering
217+ ? processTicksAndRejectionsNew
218+ : processTicksAndRejectionsOld
219+ ) ;
167220 return {
168221 nextTick,
169- runNextTicks,
222+ runNextTicks : experimentalTaskOrdering
223+ ? runNextTicksNew
224+ : runNextTicksOld ,
170225 } ;
171226 } ,
172227 queueMicrotask,
0 commit comments