proposal for shared microtask queues
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 30/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Necesita aclaración
- Estado de actividad
- Activo
- Stack tecnológico
- javascript, node.js
Línea de trabajo
Comience con los puntos de entrada de node:vm mostrados aquí: createContext, runInContext, microtaskMode y la API createMicrotaskQueue propuesta. Revise el prototipo enlazado y compare su comportamiento con el ejemplo de orden proporcionado, incluidas las limitaciones de process._tickCallback(). Se considera terminado cuando un diseño público acordado puede proporcionar un punto de control síncrono para una cola compartida sin drenar trabajo no relacionado.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
#34023 added microtaskMode: 'afterEvaluate', which gives a context its own microtask queue and drains it after evaluation. There was discussion about giving authors broader control over the queue, but that was ultimately left out as beyond what users seemed to need.
However, the HTML Standard is riddled with requirements that need this kind of control. For example, HTML assigns a microtask queue to each event loop. Its clean up after running script algorithm then requires:
- Finishing a script removes its realm execution context from the stack.
- If the stack is then empty, the event loop performs a microtask checkpoint.
A Window and its same-agent iframe have separate realms but share an event loop. If they are represented by separate vm.Contexts, they therefore need one shared microtask queue.
Currently there's just not enough control over when queues are drained:
- Default contexts share Node's queue, but there is no public API to synchronously drain it.
afterEvaluatedrains synchronously, but gives every context a separate queue.
Let's try to explore this with code.
const vm = require('node:vm');
function run(options, drain = () => {}) {
const trace = [];
const record = (entry) => trace.push(entry);
const window = vm.createContext({ record }, options);
const iframe = vm.createContext({ record }, options);
vm.runInContext(`
const pending = new Promise((resolve) => {
globalThis.resolve = resolve;
});
pending.then(() => {
record('win-rxn');
Promise.resolve().then(() => record('win-follow-up'));
});
`, window);
vm.runInContext(`
const pending = new Promise((resolve) => {
globalThis.resolve = resolve;
});
pending.then(() => record('iframe-rxn'));
`, iframe);
window.resolveIframe = iframe.resolve;
vm.runInContext('resolve(); resolveIframe();', window);
drain(iframe);
return trace;
}
console.log(run());
// []
console.log(run(
{ microtaskMode: 'afterEvaluate' },
(iframe) => vm.runInContext('', iframe),
));
// ['win-rxn', 'win-follow-up', 'iframe-rxn']
The HTML model instead requires:
['win-rxn', 'iframe-rxn', 'win-follow-up']
With default contexts, both reactions are placed on Node's shared microtask queue in the required order, but there is no supported public API for performing the required checkpoint before run() returns. That is why the first call returns [].
With afterEvaluate, returning from the Window evaluation immediately drains the Window's private queue to exhaustion. The Window reaction therefore runs its follow-up before the iframe's private queue can be drained:
['win-rxn', 'win-follow-up', 'iframe-rxn']
Even if the iframe's private queue could be drained before the Window's, that would merely reverse the problem:
['iframe-rxn', 'win-rxn', 'win-follow-up']
Node's public vm therefore cannot perform this synchronous shared-queue checkpoint. Well, it isn't entirely impossible to make this example pass: process._tickCallback() does it. I initially thought that might be an acceptable hack for my own code, but it's deprecated and, after trying to build an actual event loop around it, looks DOA as a general solution because it’s a club when I needed a sewing needle (it drains Node’s shared nextTick and microtask queues, including work unrelated to the checkpoint).
My proposal is to expose a queue that multiple contexts can share and let authors be responsible for the draining. Something like:
const queue = vm.createMicrotaskQueue();
console.log(run(
{ microtaskQueue: queue },
() => queue.runMicrotasks(),
));
// ['win-rxn', 'iframe-rxn', 'win-follow-up']
I do have a working prototype dreamed up with AI assist, but Node/V8 embedding internals are honestly outside my working knowledge.
- Lenguaje dominante
- JavaScript
- Estrellas
- 122k
- Forks
- 37.4k
- Merge medio
- 4 d 4 h
- PR fusionados (30 d)
- 276
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de nodejs/node
-
doc
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
-
build
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 90/100
-
feature request
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Todos los issues de nodejs/node
Issues similares
-
bug customer-eng Durable Agents Inngest status: needs triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
optimization optimization:agents-md-curator
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
githubnext/gh-aw-cao#13475 ·
-
[BUG]: "Clear All" in Settings doesn't clear the saved analysis, old data comes back after reload Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
AOSSIE-Org/OrgExplorer#253 · 1 comentario ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
oxc-project/oxc#26944 ·
-
ai-observability bug team/ai-observability
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100