From ec4b4f5a642c06e1944baac223057091ddba2df1 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Thu, 10 Sep 2026 13:14:20 +0200 Subject: [PATCH] vm: support shared microtask queues Add `vm.MicrotaskQueue` and `options.microtaskQueue` to allow multiple contexts to share an explicit V8 microtask queue and let users control synchronous checkpoint draining. Document how options.microtaskQueue and options.microtaskMode interact across createContext, runInNewContext, and script.runInNewContext. Update receiver type error expectation for runMicrotasks and add test coverage for runInNewContext with microtask queues. Fixes: https://github.com/nodejs/node/issues/65555 Signed-off-by: Alessio Attilio Assisted-by: Antigravity --- doc/api/vm.md | 97 +++++++++- lib/vm.js | 36 +++- src/env_properties.h | 1 + src/node_contextify.cc | 98 ++++++++++- src/node_contextify.h | 36 +++- .../test-vm-shared-microtask-queue.js | 165 ++++++++++++++++++ 6 files changed, 422 insertions(+), 11 deletions(-) create mode 100644 test/parallel/test-vm-shared-microtask-queue.js diff --git a/doc/api/vm.md b/doc/api/vm.md index 14cd1f269b12..0d74a4caba22 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -316,7 +316,19 @@ changes: * `microtaskMode` {string} If set to `afterEvaluate`, microtasks (tasks scheduled through `Promise`s and `async function`s) will be run immediately after the script has run. They are included in the `timeout` and - `breakOnSigint` scopes in that case. + `breakOnSigint` scopes in that case. If `microtaskQueue` (or + `contextMicrotaskQueue`) is also specified, evaluating the script will + drain that shared microtask queue (including any microtasks queued from + other contexts sharing the queue). If `microtaskQueue` is not specified, a + private microtask queue is created exclusively for this context. + * `microtaskQueue` {vm.MicrotaskQueue} A microtask queue created with + [`new vm.MicrotaskQueue()`][] or [`vm.createMicrotaskQueue()`][]. If + specified, microtasks scheduled inside the new context will be placed on + this queue. By default, microtasks placed on this queue are not + automatically drained when script evaluation finishes; they remain queued + until explicitly drained using [`microtaskQueue.runMicrotasks()`][], unless + `microtaskMode: 'afterEvaluate'` is also specified. An alias for this + option is `contextMicrotaskQueue`. * Returns: {any} the result of the very last statement executed in the script. This method is a shortcut to `script.runInContext(vm.createContext(options), options)`. @@ -1318,6 +1330,37 @@ added: A `ModuleRequest` represents the request to import a module with given import attributes and phase. +## Class: `vm.MicrotaskQueue` + + + +Represents an explicit microtask queue that can be shared across multiple +`vm.Context` instances and synchronously drained by the embedder. + +By default, passing a `vm.MicrotaskQueue` to [`vm.createContext()`][] attaches the +context to that queue without automatically draining it after script evaluation; +microtasks remain queued until explicitly drained using +[`microtaskQueue.runMicrotasks()`][]. If automatic draining upon script completion +is also desired, pass `microtaskMode: 'afterEvaluate'` alongside `microtaskQueue`. + +### `new vm.MicrotaskQueue()` + + + +Creates a new `vm.MicrotaskQueue` instance. + +### `microtaskQueue.runMicrotasks()` + + + +Synchronously runs all microtasks currently queued in this microtask queue. + ## `vm.compileFunction(code[, params[, options]])` + +* Returns: {vm.MicrotaskQueue} + +Creates a new [`vm.MicrotaskQueue`][] instance. Shortcut to +`new vm.MicrotaskQueue()`. + +## `vm.isMicrotaskQueue(object)` + + + +* `object` {any} +* Returns: {boolean} + +Returns `true` if the given `object` is an instance of [`vm.MicrotaskQueue`][]. + ## `vm.measureMemory([options])`