Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

proposal for shared microtask queues

未關閉
#65,555 2 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
5/5
預估耗時
一週以上
新手友好度
30/100
Issue 類型
功能
描述清晰度
需要釐清
活躍度
活躍
技術堆疊
javascript, node.js
領域
api, backend

研究方向

從這裡顯示的 node:vm 進入點開始:createContext、runInContext、microtaskMode,以及提議的 createMicrotaskQueue API。檢視連結的原型,並將其行為與提供的排序範例進行比較,包括 process._tickCallback() 的限制。當達成共識的公開設計能夠提供共用佇列的同步檢查點,且不會清空無關工作時,即視為完成。

由索引模型根據 Issue 內容生成。

描述

feature request vm

#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.
  • afterEvaluate drains 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.

主要語言
JavaScript
星號
122k
分支
37.4k
平均合併
4 天 8 小時
30 天內合併 PR
293

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

nodejs/node 的其他 Issue

查看 nodejs/node 的全部 Issue

相似的 Issue

更多 JavaScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。