@@ -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,25 @@ 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+ function runNextTicksOld ( ) {
69+ if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
70+ runMicrotasks ( ) ;
71+ if ( ! hasTickScheduled ( ) && ! hasRejectionToWarn ( ) )
72+ return ;
73+
74+ processTicksAndRejectionsOld ( ) ;
75+ }
76+
77+ function processTicksAndRejectionsOld ( ) {
6878 let tock ;
6979 do {
7080 while ( ( tock = queue . shift ( ) ) !== null ) {
@@ -98,6 +108,40 @@ function processTicksAndRejections() {
98108 setHasRejectionToWarn ( false ) ;
99109}
100110
111+ function processTicksAndRejectionsNew ( ) {
112+ let tock ;
113+ do {
114+ runMicrotasks ( ) ;
115+ while ( ( tock = queue . shift ( ) ) !== null ) {
116+ const asyncId = tock [ async_id_symbol ] ;
117+ emitBefore ( asyncId , tock [ trigger_async_id_symbol ] , tock ) ;
118+
119+ try {
120+ const callback = tock . callback ;
121+ if ( tock . args === undefined ) {
122+ callback ( ) ;
123+ } else {
124+ const args = tock . args ;
125+ switch ( args . length ) {
126+ case 1 : callback ( args [ 0 ] ) ; break ;
127+ case 2 : callback ( args [ 0 ] , args [ 1 ] ) ; break ;
128+ case 3 : callback ( args [ 0 ] , args [ 1 ] , args [ 2 ] ) ; break ;
129+ case 4 : callback ( args [ 0 ] , args [ 1 ] , args [ 2 ] , args [ 3 ] ) ; break ;
130+ default : callback ( ...args ) ;
131+ }
132+ }
133+ } finally {
134+ if ( destroyHooksExist ( ) )
135+ emitDestroy ( asyncId ) ;
136+ }
137+
138+ emitAfter ( asyncId ) ;
139+ }
140+ } while ( ! queue . isEmpty ( ) || processPromiseRejections ( ) ) ;
141+ setHasTickScheduled ( false ) ;
142+ setHasRejectionToWarn ( false ) ;
143+ }
144+
101145// `nextTick()` will not enqueue any callback when the process is about to
102146// exit since the callback would not have a chance to be executed.
103147function nextTick ( callback ) {
@@ -160,13 +204,23 @@ function queueMicrotask(callback) {
160204
161205module . exports = {
162206 setupTaskQueue ( ) {
207+ if ( experimentalTaskOrdering === undefined ) {
208+ const { getOptionValue } = require ( 'internal/options' ) ;
209+ experimentalTaskOrdering = getOptionValue ( '--experimental-task-ordering' ) ;
210+ }
211+
163212 // Sets the per-isolate promise rejection callback
164213 listenForRejections ( ) ;
165214 // Sets the callback to be run in every tick.
166- setTickCallback ( processTicksAndRejections ) ;
215+ setTickCallback ( experimentalTaskOrdering
216+ ? processTicksAndRejectionsNew
217+ : processTicksAndRejectionsOld
218+ ) ;
167219 return {
168220 nextTick,
169- runNextTicks,
221+ runNextTicks : experimentalTaskOrdering
222+ ? runNextTicksNew
223+ : runNextTicksOld ,
170224 } ;
171225 } ,
172226 queueMicrotask,
0 commit comments