Skip to content

Commit

Permalink
lib: run microtasks before ticks
Browse files Browse the repository at this point in the history
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
  • Loading branch information
ronag committed Dec 24, 2023
1 parent fc102f2 commit 6fedd50
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
15 changes: 15 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,21 @@ about [this configuration][`--experimental-sea-config`] for details.

### `--experimental-shadow-realm`

### `--experimental-task-ordering`

Enable experimental task ordering. Always drain micro task queue
before running `process.nextTick` to avoid unintuitive behavior
and unexpected logical deadlocks when mixing async callback and
event API's with `Promise`, `async`/`await`` and `queueMicroTask`.

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental


<!-- YAML
added:
- v19.0.0
Expand Down
13 changes: 12 additions & 1 deletion lib/internal/process/task_queues.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const {

const { AsyncResource } = require('async_hooks');

let experimentalTaskOrdering;
// *Must* match Environment::TickInfo::Fields in src/env.h.
const kHasTickScheduled = 0;

Expand All @@ -65,8 +66,16 @@ function runNextTicks() {
}

function processTicksAndRejections() {
if (experimentalTaskOrdering === undeifned) {
const { getOptionValue } = require('internal/options');
experimentalTaskOrdering = getOptionValue('--experimental-task-ordering');
}

let tock;
do {
if (experimentalTaskOrdering) {
runMicrotasks();
}
while ((tock = queue.shift()) !== null) {
const asyncId = tock[async_id_symbol];
emitBefore(asyncId, tock[trigger_async_id_symbol], tock);
Expand All @@ -92,7 +101,9 @@ function processTicksAndRejections() {

emitAfter(asyncId);
}
runMicrotasks();
if (!experimentalTaskOrdering) {
runMicrotasks();
}
} while (!queue.isEmpty() || processPromiseRejections());
setHasTickScheduled(false);
setHasRejectionToWarn(false);
Expand Down

0 comments on commit 6fedd50

Please sign in to comment.