11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { 41cb0ef41Sopenharmony_ci Array, 51cb0ef41Sopenharmony_ci FunctionPrototypeBind, 61cb0ef41Sopenharmony_ci} = primordials; 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciconst { 91cb0ef41Sopenharmony_ci // For easy access to the nextTick state in the C++ land, 101cb0ef41Sopenharmony_ci // and to avoid unnecessary calls into JS land. 111cb0ef41Sopenharmony_ci tickInfo, 121cb0ef41Sopenharmony_ci // Used to run V8's micro task queue. 131cb0ef41Sopenharmony_ci runMicrotasks, 141cb0ef41Sopenharmony_ci setTickCallback, 151cb0ef41Sopenharmony_ci enqueueMicrotask, 161cb0ef41Sopenharmony_ci} = internalBinding('task_queue'); 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciconst { 191cb0ef41Sopenharmony_ci setHasRejectionToWarn, 201cb0ef41Sopenharmony_ci hasRejectionToWarn, 211cb0ef41Sopenharmony_ci listenForRejections, 221cb0ef41Sopenharmony_ci processPromiseRejections, 231cb0ef41Sopenharmony_ci} = require('internal/process/promises'); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciconst { 261cb0ef41Sopenharmony_ci getDefaultTriggerAsyncId, 271cb0ef41Sopenharmony_ci newAsyncId, 281cb0ef41Sopenharmony_ci initHooksExist, 291cb0ef41Sopenharmony_ci destroyHooksExist, 301cb0ef41Sopenharmony_ci emitInit, 311cb0ef41Sopenharmony_ci emitBefore, 321cb0ef41Sopenharmony_ci emitAfter, 331cb0ef41Sopenharmony_ci emitDestroy, 341cb0ef41Sopenharmony_ci symbols: { async_id_symbol, trigger_async_id_symbol }, 351cb0ef41Sopenharmony_ci} = require('internal/async_hooks'); 361cb0ef41Sopenharmony_ciconst FixedQueue = require('internal/fixed_queue'); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ciconst { 391cb0ef41Sopenharmony_ci validateFunction, 401cb0ef41Sopenharmony_ci} = require('internal/validators'); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ciconst { AsyncResource } = require('async_hooks'); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci// *Must* match Environment::TickInfo::Fields in src/env.h. 451cb0ef41Sopenharmony_ciconst kHasTickScheduled = 0; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_cifunction hasTickScheduled() { 481cb0ef41Sopenharmony_ci return tickInfo[kHasTickScheduled] === 1; 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_cifunction setHasTickScheduled(value) { 521cb0ef41Sopenharmony_ci tickInfo[kHasTickScheduled] = value ? 1 : 0; 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ciconst queue = new FixedQueue(); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci// Should be in sync with RunNextTicksNative in node_task_queue.cc 581cb0ef41Sopenharmony_cifunction runNextTicks() { 591cb0ef41Sopenharmony_ci if (!hasTickScheduled() && !hasRejectionToWarn()) 601cb0ef41Sopenharmony_ci runMicrotasks(); 611cb0ef41Sopenharmony_ci if (!hasTickScheduled() && !hasRejectionToWarn()) 621cb0ef41Sopenharmony_ci return; 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci processTicksAndRejections(); 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_cifunction processTicksAndRejections() { 681cb0ef41Sopenharmony_ci let tock; 691cb0ef41Sopenharmony_ci do { 701cb0ef41Sopenharmony_ci while ((tock = queue.shift()) !== null) { 711cb0ef41Sopenharmony_ci const asyncId = tock[async_id_symbol]; 721cb0ef41Sopenharmony_ci emitBefore(asyncId, tock[trigger_async_id_symbol], tock); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci try { 751cb0ef41Sopenharmony_ci const callback = tock.callback; 761cb0ef41Sopenharmony_ci if (tock.args === undefined) { 771cb0ef41Sopenharmony_ci callback(); 781cb0ef41Sopenharmony_ci } else { 791cb0ef41Sopenharmony_ci const args = tock.args; 801cb0ef41Sopenharmony_ci switch (args.length) { 811cb0ef41Sopenharmony_ci case 1: callback(args[0]); break; 821cb0ef41Sopenharmony_ci case 2: callback(args[0], args[1]); break; 831cb0ef41Sopenharmony_ci case 3: callback(args[0], args[1], args[2]); break; 841cb0ef41Sopenharmony_ci case 4: callback(args[0], args[1], args[2], args[3]); break; 851cb0ef41Sopenharmony_ci default: callback(...args); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci } finally { 891cb0ef41Sopenharmony_ci if (destroyHooksExist()) 901cb0ef41Sopenharmony_ci emitDestroy(asyncId); 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci emitAfter(asyncId); 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci runMicrotasks(); 961cb0ef41Sopenharmony_ci } while (!queue.isEmpty() || processPromiseRejections()); 971cb0ef41Sopenharmony_ci setHasTickScheduled(false); 981cb0ef41Sopenharmony_ci setHasRejectionToWarn(false); 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci// `nextTick()` will not enqueue any callback when the process is about to 1021cb0ef41Sopenharmony_ci// exit since the callback would not have a chance to be executed. 1031cb0ef41Sopenharmony_cifunction nextTick(callback) { 1041cb0ef41Sopenharmony_ci validateFunction(callback, 'callback'); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci if (process._exiting) 1071cb0ef41Sopenharmony_ci return; 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci let args; 1101cb0ef41Sopenharmony_ci switch (arguments.length) { 1111cb0ef41Sopenharmony_ci case 1: break; 1121cb0ef41Sopenharmony_ci case 2: args = [arguments[1]]; break; 1131cb0ef41Sopenharmony_ci case 3: args = [arguments[1], arguments[2]]; break; 1141cb0ef41Sopenharmony_ci case 4: args = [arguments[1], arguments[2], arguments[3]]; break; 1151cb0ef41Sopenharmony_ci default: 1161cb0ef41Sopenharmony_ci args = new Array(arguments.length - 1); 1171cb0ef41Sopenharmony_ci for (let i = 1; i < arguments.length; i++) 1181cb0ef41Sopenharmony_ci args[i - 1] = arguments[i]; 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci if (queue.isEmpty()) 1221cb0ef41Sopenharmony_ci setHasTickScheduled(true); 1231cb0ef41Sopenharmony_ci const asyncId = newAsyncId(); 1241cb0ef41Sopenharmony_ci const triggerAsyncId = getDefaultTriggerAsyncId(); 1251cb0ef41Sopenharmony_ci const tickObject = { 1261cb0ef41Sopenharmony_ci [async_id_symbol]: asyncId, 1271cb0ef41Sopenharmony_ci [trigger_async_id_symbol]: triggerAsyncId, 1281cb0ef41Sopenharmony_ci callback, 1291cb0ef41Sopenharmony_ci args, 1301cb0ef41Sopenharmony_ci }; 1311cb0ef41Sopenharmony_ci if (initHooksExist()) 1321cb0ef41Sopenharmony_ci emitInit(asyncId, 'TickObject', triggerAsyncId, tickObject); 1331cb0ef41Sopenharmony_ci queue.push(tickObject); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_cifunction runMicrotask() { 1371cb0ef41Sopenharmony_ci this.runInAsyncScope(() => { 1381cb0ef41Sopenharmony_ci const callback = this.callback; 1391cb0ef41Sopenharmony_ci try { 1401cb0ef41Sopenharmony_ci callback(); 1411cb0ef41Sopenharmony_ci } finally { 1421cb0ef41Sopenharmony_ci this.emitDestroy(); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci }); 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ciconst defaultMicrotaskResourceOpts = { requireManualDestroy: true }; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_cifunction queueMicrotask(callback) { 1501cb0ef41Sopenharmony_ci validateFunction(callback, 'callback'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci const asyncResource = new AsyncResource( 1531cb0ef41Sopenharmony_ci 'Microtask', 1541cb0ef41Sopenharmony_ci defaultMicrotaskResourceOpts, 1551cb0ef41Sopenharmony_ci ); 1561cb0ef41Sopenharmony_ci asyncResource.callback = callback; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci enqueueMicrotask(FunctionPrototypeBind(runMicrotask, asyncResource)); 1591cb0ef41Sopenharmony_ci} 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_cimodule.exports = { 1621cb0ef41Sopenharmony_ci setupTaskQueue() { 1631cb0ef41Sopenharmony_ci // Sets the per-isolate promise rejection callback 1641cb0ef41Sopenharmony_ci listenForRejections(); 1651cb0ef41Sopenharmony_ci // Sets the callback to be run in every tick. 1661cb0ef41Sopenharmony_ci setTickCallback(processTicksAndRejections); 1671cb0ef41Sopenharmony_ci return { 1681cb0ef41Sopenharmony_ci nextTick, 1691cb0ef41Sopenharmony_ci runNextTicks, 1701cb0ef41Sopenharmony_ci }; 1711cb0ef41Sopenharmony_ci }, 1721cb0ef41Sopenharmony_ci queueMicrotask, 1731cb0ef41Sopenharmony_ci}; 174