マイクロタスクキュー

マイクロタスク (Web)

[35] マイクロタスク (microtask) は、 Webブラウザーにおける処理の単位で、 変異観測器約束などの処理で用いられています。

仕様書

マイクロタスク

[50] マイクロタスクは、最初にタスクキューではなくマイクロタスクキューに入れられたタスクです。 マイクロタスクには孤独コールバックマイクロタスク複合マイクロタスクの2種類があります。 >>49

[51] マイクロタスクが通常のタスクに比べて「マイクロ」であるのは、 タスクイベントループの全体によって順次処理されていくのに対し、 マイクロタスクのほとんどがそのイベントループの一度の繰り返しの内で順次実行されることを指しています。 マイクロタスク自体もタスクの一種なのであって、 マイクロタスクによってタスクが構成されるような階層構造にはありません

孤独コールバックマイクロタスク

[61] 孤独コールバックマイクロタスク (solitary callback microtask) は、 それ自体が実行時の最小単位のタスクとなるようなマイクロタスクです。

[100] ほとんどのマイクロタスクは、孤独コールバックマイクロタスクです。

[42] 孤独コールバックマイクロタスクには、次のものがあります。

[113] かつては次のものも予定されていました。

[120] カスタム要素コールバックマイクロタスクを使うことが一時想定されていましたが、 最終的には独自のキューを使う形となっています。

複合マイクロタスク

[62] 複合マイクロタスク (compound microtask) は、 実行時に最小単位のタスク複数個に分割され得るマイクロタスクです。

[78] 複合マイクロタスクの一部として実行されるタスクのことを、 複合マイクロタスク部分タスク (compound microtask subtask) といいます。

[77] 例えば mutation observerマイクロタスクは、複数の MutationObserver コールバックを呼び出す可能性があり、 それぞれが複合マイクロタスク部分タスクであるような1つの複合マイクロタスクとして定義されています。

[66] 複合マイクロタスクは、イベントループのスピン時の挙動を正しく扱えるように注意する必要があります。 そのために複合マイクロタスク部分タスクを実行する手順 (>>67) が用意されていて、 複合マイクロタスクを定義する仕様書はこれを参照することが期待されています。

[101] 複合マイクロタスクには、次のものがあります。

その他の処理

[97] 定義上マイクロタスクではありませんが、 マイクロタスクの実行のタイミングで実行される処理として、他に、 拒絶された約束について通知IndexedDBトランザクションの片付けがあります。

[98] これらの処理は、マイクロタスクとは違って、マイクロタスクキューを使わず毎回適宜実行されます。

マイクロタスクキュー

[53] イベントループマイクロタスクキュー (microtask queue) を (タスクキューとは別に) 持ちます。 >>49

[90] ECMAScript 仕様書は独自のジョブキュー PromiseJobs を規定していますが、これは Web におけるマイクロタスクキューに相当します。

[89] マイクロタスクをキューに入れる (queue a microtask) とは、 マイクロタスクを自イベントループマイクロタスクキューの末尾に追加することをいいます。 >>49 Web 系の仕様書は、こちらの操作を直接使っています。

[91] 抽象演算 EnqueueJob(queueName, job, arguments) は、次のようにしなければなりません >>76

  1. [93]
    ジョブ設定群を、何らかの設定群オブジェクトに設定します。
  2. [125] 現職設定群を、現職設定群オブジェクトに設定します。
  3. [114] 活性スクリプトを、活性スクリプトに設定します。
  4. [109] スクリプト実行文脈を、 新しいJavaScript実行文脈に設定します。
    [110] JavaScript実行文脈
    Function
    null
    Realm
    活性スクリプト設定群オブジェクトRealm
    ScriptOrModule
    活性スクリプト記録
  5. [94] ジョブ設定群有責イベントループについて、 マイクロタスクをキューに追加します。
    マイクロタスク
    処理
    1. [128] ジョブ設定群現職設定群jobargumentsスクリプト実行文脈について、約束コールバックを実行します。

[99] ECMAScript 仕様書は、こちらの操作を使っています。 queueNamesPromiseJobsScriptJobs 規定されていますが、 Web では PromiseJobs しか使いません。

[92] Webイベントループと統合されたこのアルゴリズムは HTML Standard の独自の規定であり、 ECMAScript 仕様書への意図的違反 >>76 とされています。

マイクロタスクタスク源

[54] マイクロタスクタスク源マイクロタスクタスク源 (microtask task source) となります。 >>49 マイクロタスクキューにはタスク源は関係してこないので、ほとんどのマイクロタスクタスク源と無関係ですが、 マイクロタスクタスクキューに移されるとタスク源が関係してきます。

マイクロタスクの実行

[102] マイクロタスクは、マイクロタスクチェックポイントを行う手続きにより、 マイクロタスクキューの順番で実行されます。

[12] イベントループについてマイクロタスクチェックポイントを行う (perform a microtask checkpoint) 際には次のようにしなければなりません >>7

  1. [8] イベントループマイクロタスクチェックポイントを行っているフラグなら、ここで停止します。
  2. [9] イベントループマイクロタスクチェックポイントを行っているフラグにします。
  3. [55] イベントループマイクロタスクキューが空でない間、繰り返し、 次の通り実行します。
    1. [56] タスクを、イベントループマイクロタスクキューの最古のマイクロタスクに設定します。
    2. [63] イベントループ現在走っているタスクを、タスクに設定します。
    3. [64] タスクを実行します。
    4. [65] イベントループ現在走っているタスクを、 null に設定します。
    5. [58] イベントループマイクロタスクキューからタスクを削除します。
  4. [32] イベントループ環境設定群オブジェクトの各設定群について、
    1. [36] 設定群拒絶された約束について通知します。
  5. [96] イベントループIndexedDBトランザクションの片付けをします。
  6. [13] イベントループマイクロタスクチェックポイントを行っているフラグにします。

[34] イベントループマイクロタスクチェックポイントを行っている (performing a microtask checkpoint) フラグを持っており、初期値はです。 >>7

[11] マイクロタスクによってコールバックスクリプトが呼び出されたりするわけですが、 その際 jump to a code entry-point アルゴリズムが呼ばれ、 その中で再度マイクロタスクチェックポイントが呼ばれることになるので、 マイクロタスクチェックポイントを行っているフラグでチェックして再実行しないようにしています。

[15] マイクロタスクチェックポイントを行うのは次の場面です。

[19] SVG script 要素でも同様に呼び出されるものと推察されますが、 現時点で SVG script 要素の処理モデルを詳細に規定した仕様がありません。

[82] つまりマイクロタスクは、スクリプトタスクの前後に実行されます。 複数のマイクロタスクがあれば、それらをすべて実行してから次のタスクへと進みます。

[103] これがマイクロタスクの「マイクロ」たる所以と思われます。

複合マイクロタスク部分タスクの実行

[67] 指定された手順について複合マイクロタスク部分タスクを実行する (execute a compound microtask subtask) とは次のような手順をいいます >>7

  1. [68] parent現在走っているタスクとします。
    1. [69] これは本手順を呼び出している複合マイクロタスクとなります。
  2. [70] subtask を指定された手順を実行するタスクとします。 これが複合マイクロタスク部分タスクです。 タスク源マイクロタスクタスク源とします。
  3. [71] 現在走っているタスクsubtask とします。
  4. [72] subtask を実行します。
  5. [73] 現在走っているタスクparent とします。

[79] この手順はすなわち、「ある手順をその場でタスクとして実行する」ということになります。 複合マイクロタスクはそれ自体の手順の中で、複合マイクロタスク部分タスクとして実行したい部分を >>67 の手順で“包んで”実行することになります。これはスピンの挙動を定義するためであり、 ただの孤独コールバックタスク複合マイクロタスクが異なるのはスピンに対する挙動だけです。 スピンは実行中のタスクを終了させ、続きの実行を後回しにします。この後で実行する単位が、 >>67 によって当該複合マイクロタスク部分タスクだけに限定されます。 mutation observer の場合だと、当該 MutationObserver だけが中断され、他の MutationObserver があればそれらは即座に実行されます。

関連

[59] マイクロタスクキューとは別に、タスクキューなるものもあります。

[80] 大域スクリプト片付けジョブマイクロタスクと似ていて同じようなタイミングで実行されますが、 異なるタイミングで実行されることもあります。

[38] 拒絶された約束について通知は、マイクロタスクではありませんが、 マイクロタスクが実行されるタイミングでマイクロタスクの後に実行され、 実質的に特別なマイクロタスクとなっています。

歴史

[37] マイクロタスク変異観測器のための仕組みとして HTML Standard に導入されました。

[39] blob: についてもマイクロタスクチェックポイントでの処理が検討されましたが、 global script clean-up jobs list という新しい仕組みになりました。

[41] ここまで仕様書上マイクロタスクと呼ばれるものはなく、 マイクロタスクチェックポイントの一連の処理として定義されていました (>>12)。

[52] しかし >>48 によってタスクの一種としてマイクロタスクが定義されるようになりました。 マイクロタスクキューが導入され、マイクロタスクが後に通常のタスクキューによって処理され得る単位となったのもこの時です。 それに加えて >>60 により、複合マイクロタスクが導入され、 マイクロタスクの一部分が複合マイクロタスク部分タスクとして実行されるケースが生じました。

[75] >>74マイクロタスクはメインのイベントループだけでなく、ワーカーでも実行可能となりました。

[5] >>4安定状態を提供するもの以外でもアルゴリズムの途中からの継続にマイクロタスクが使われるようになっています。

[10] >>6XHRtimeoutマイクロタスクとして再定義されました。

[87] Re: Indexed DB Transactions vs. Microtasks ( (Jonas Sicking 著, 版)) <http://lists.w3.org/Archives/Public/public-webapps/2014AprJun/0861.html>

[108] The "initialization" steps for Web browsers ( ( 版)) <https://mail.mozilla.org/pipermail/es-discuss/2014-June/037554.html>

[88] Bug 25714 - [Custom]: Move microtask processing to compound microtask · ffeeba6 · w3c/webcomponents ( ( 版)) <https://github.com/w3c/webcomponents/commit/ffeeba6b1a3446ebc183a0ae2b7ee8445e44635d>

[22] IRC logs: freenode / #whatwg / 20150120 ( 版) <http://krijnhoetmer.nl/irc-logs/whatwg/20150120#l-658>

[28] IRC logs: freenode / #whatwg / 20150811 ( 版) <http://krijnhoetmer.nl/irc-logs/whatwg/20150811>

# [11:34] <JakeA> Chrome's implementation performs a microtask checkpoint per listener, Firefox doesn't

[30] Tasks, microtasks, queues and schedules - JakeArchibald.com ( 版) <https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/>

Firefox and Safari are correctly exhausting the microtask queue between click listeners, as shown by the mutation callbacks, but promises appear to be queued differently. This is sort-of excusable given that the link between jobs & microtasks is vague, but I'd still expect them to execute between listener callbacks. Firefox ticket. Safari ticket.

With Edge we've already seen it queue promises incorrectly, but it also fails to exhaust the microtask queue between click listeners, instead it does so after calling all listeners, which accounts for the single mutate log after both click logs. Bug ticket.

[31] Add promise rejection tracking events · whatwg/html@61ccc05 ( 版) <https://github.com/whatwg/html/commit/61ccc05b7437ba947390928f9e526da49550fed0>

[57] Remove the storage mutex due to lack of implementation · whatwg/html@1b918cf ( 版) <https://github.com/whatwg/html/commit/1b918cf72fcbba011f83b92ab5d1f483fb1cafa3>

[111] Add <script type="module"> and module resolution/fetching/evaluation · whatwg/html@cd1a9fb ( 版) <https://github.com/whatwg/html/commit/cd1a9fb1e83f7d0bc30be8b34ecdaf444a0b19a4>

[112] Fix #345: Remove table sorting model · whatwg/html@59b7e24 ( 版) <https://github.com/whatwg/html/commit/59b7e2466c2b7c5c408a4963b05b13fd808aa07a>

[115] Sync with recent changes to the JS spec's job queue · whatwg/html@5af258f ( 版) <https://github.com/whatwg/html/commit/5af258f33e3e2f55eb30e611cb7aee625a8bd16a>

[118] Clarify settings object, realm, and global relationships · whatwg/html@0866f1b ( 版) <https://github.com/whatwg/html/commit/0866f1b3f4b4ea5a99a30909e9bbe557dea0b460>

[119] 1193394 – Microtasks and promises ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=1193394>

[122] Unclear if microtasks are running as often as they should · Issue #1294 · whatwg/html ( ()) <https://github.com/whatwg/html/issues/1294>

[123] Add a new section detailing the various potential realms (domenic著, ) <https://github.com/whatwg/html/commit/6399af334edd6000bd394685923df5f0519194ab>

[124] Fix incumbent settings object definition and add examples (domenic著, ) <https://github.com/whatwg/html/commit/f97c3e478654114bd4c9cc8587418a5519f9eb09>

[95] Re: Compound microtasks vs solitary microtasks (Ian Hickson著, ) <https://lists.w3.org/Archives/Public/www-archive/2016Oct/0001.html>

[104] Improve the wording around handling timeouts (annevk著, ) <https://github.com/whatwg/xhr/commit/4d40787e39eb872de30e40110d1201f90c4beecb>

[105] Editorial: modernize perform a microtask checkpoint (annevk著, ) <https://github.com/whatwg/html/commit/eb31d93fdf569da9b8529a79c3060868a15fa328>

[106] 28920 – If the stack of script settings objects is empty, perform a microtask checkpoint right before executing async or defer script () <https://www.w3.org/Bugs/Public/show_bug.cgi?id=28920>

[107] 1193394 - Microtasks and promises () <https://bugzilla.mozilla.org/show_bug.cgi?id=1193394>

[116] Ensure there is an active script while running JS jobs (domenic著, ) <https://github.com/whatwg/html/commit/cc3fcc87a7c6f8783efa327b449d7381a0e0303d>

[117] Ensure there is an active script while running JS jobs (domenic著, ) <https://github.com/whatwg/html/commit/cc3fcc87a7c6f8783efa327b449d7381a0e0303d>

[126] Ensure there is an active script while running JS jobs by domenic · Pull Request #3163 · whatwg/html () <https://github.com/whatwg/html/pull/3163>

[127] Ensure there is an active script while running JS jobs by domenic · Pull Request #3163 · whatwg/html () <https://github.com/whatwg/html/pull/3163>

[129] Ensure there is an active script while running JS jobs by domenic · Pull Request #3163 · whatwg/html () <https://github.com/whatwg/html/pull/3163>

[130] Ensure there is an active script while running JS jobs by domenic · Pull Request #3163 · whatwg/html () <https://github.com/whatwg/html/pull/3163>

[131] Proposal: self.queueMicrotask(f) · Issue #512 · whatwg/html () <https://github.com/whatwg/html/issues/512>