task queue

タスクキュー (Web)

[2] タスクキュー (task queue) は、イベントループにおけるタスク順序付きリスト (キュー) です。 Webブラウザー内に常にいくつか存在します。

仕様書

意味

[4] タスクキューは、タスク集合です >>1。 0個以上のタスクを入れたり出したりできます。 原則的に FIFO なのでキューと呼ばれていますが、 event loop step 1 のようにそれ以外の特別な操作もあるため、 現在の HTML Standard集合と定義しています >>1。 なお Infra Standard によれば Web における集合順序付きリストです。

[5] 基本的に未実行のタスクタスクキューに入れられて待機状態となります。 一つのタスクが複数のタスクキューに同時に含まれることはありません。

文脈

[18] イベントループは、1つ以上タスクキュー群を持ちます >>1

[31] イベントループがいくつタスクキューを持つかは、実装依存です。

[12] 例えば、マウス操作その他の利用者の操作 (利用者対話タスク源) のタスクキューと、それ以外のタスクキューとで2つ用意し、 利用者の操作のタスクキューを優先的に処理する、という戦略を採ることができます。 >>1

[32] あるイベントループで、 あるタスク源から来たタスクをどのタスクキューに追加するかは、 実装依存の方法で固定しなければなりません >>1 (>>3)。

[84] 実装戦略によっては実行時にタスクキューが増減するかもしれませんが、 同じタスク源タスクは同じタスクキューに入れなければならないという原則は歪められません。


[76] サービスワーカー登録は、1つ以上タスクキュー群 (task queues) を持ちます。 これは活性ワーカーが動作していない間にタスクを保持しておくもので、 これ自体を使ってタスクを実行するものではありません。 >>75

タスク源

[46]タスクは、何らかのタスク源 (task source) から来る (come) ものと定義されます >>44

[102] タスクは、 (source) を持ちます。 は、 タスク源のいずれかであって、 関連するタスクを集団化し直列化するために使われます。 >>9

[103] あるイベントループにおいてあるタスク源は、 当該イベントループの特定のタスクキューと関連付けられなければなりません >>9。 この関係はイベントループが開始された時から終了する時まで変わることがありません。

[104] いわばタスク源タスクキューのラベルのような働きを持っています。 タスク源には1つタスクキューがありますが、 タスクキュータスク源は1つとは限りません。 複数のタスク源が同じタスクキューを共有することがあります。 すべてのタスク源が独立したタスクキューを持つ状態が、 タスクキューを最大限分割した状態といえます。

[61] タスクキュータスク源によって分けられており、 同じタスク源タスク同士の実行順序はタスクキューへの追加順序となることが保証されます。

[62] タスク源は、追加時にタスクキューの決定に使われる他、 何らかの理由でタスクキューからタスクを削除する条件として使われることもあります。

[49] タスク源としては次のものがあります。

[53] タスク源の一覧は >>54 にあります。

[50] ほとんどのタスク源イベントループに1つずつ存在していますが、 ポートメッセージキュー著者MessagePort オブジェクトを作成することによって任意個作成されます。 クライアントメッセージキューServiceWorkerContainer オブジェクトの数だけ存在します。 媒体要素イベントタスク源XMLHttpRequestタスク源 もオブジェクトごとに存在します。 FileReaderタスク源FileSaverタスク源もオブジェクトごとに存在するようです。

[51] 未出荷済みポートメッセージキュー仮想 (virtual) タスク源 >>54 であり、そのタスクポートメッセージキューにも未出荷済みポートメッセージキューにも属するという特殊な状態になっています。 未出荷済みポートメッセージキューイベントループごとに1つだけあります >>45

[52] 転送していない MessagePort では必ず同じ順序でタスクが実行されることを保証し、 転送してしまった MessagePort では任意の実行順序となることを認めるためにこのような複雑な構造になっています。
[88] 同じタスク源なら同じタスクキューを使うとの制約から、 未出荷済みポートメッセージキューに入るタスクは (ポートメッセージキューに関わらず) 同じタスクキューに入るものとしなければなりません。出荷済みのポートメッセージキューにはこの制約はありません。

マイクロタスクとの関係

[58] マイクロタスクタスク源はすべてマイクロタスクタスク源と定義されています。

[59] マイクロタスクにはタスクキューとは別のマイクロタスクキューが存在しています。 これはマイクロタスク源タスク (マイクロタスク) を実行するタスクキューとは別のものです。

タスクキューの構造

[83] 仕様書上、タスクキュータスク集合であるとしか説明されていません。 しかし、タスクキュー上のタスクには、文書fetch という情報が関連付けられていて、これがタスクキューが関わる色々な演算で重要な役目を持ちます。

[85] タスクキューは、文書fetch という情報を持ったタスクキューであるが、 通常のキューとは異なる特殊な演算も持つ、と解釈することもできますし、 文書fetch をキーとするタスクのリスト (タスクキュー部分リスト) をいくつか重ね合わせて全体として順序を持つリストとして捉えたものがタスクキューである、 と解釈することもできそうです。

[86] ポートメッセージキュークライアントメッセージキューは、タスクキュー部分リストの一種であると解せます。

[87] 未出荷済みポートメッセージキューは、いくつかのポートメッセージキューを束ねたものと捉えることができます。 ただし、未出荷済みポートメッセージキュータスクと各ポートメッセージキュータスクが異なるタスクキューを利用する場合を考えると、 事情は若干複雑化します。

[65] タスクキュー部分リストは、状態を持ちます (>>66)。

追加

[11] タスクをキューに (つい) () (queue a task) する処理 >>1 は、新たにタスクの実行を予定するものです。

[43] タスクは、その処理に関係するイベントループに追加されます。 Webブラウザーが複数のイベントループを持つ場合、 処理対象の文書ワーカーを担当しているイベントループタスクキューに追加されることになります。

[3] タスクは、その出自であるタスク源によって決まるタスクキューに追加されます。 イベントループが複数のタスクキューを持つ場合、 同じタスク源からのタスクは必ず同じタスクキューに追加され、 相互の順序は保持されますが、 異なるタスク源からのタスクは異なるタスクキューに追加されるかもしれないため、 順序は保証されません。

[37] タスクをキューに追加する処理は、 次の引数を受け取ります。

タスク源
イベントループ
イベントループ仕様書はこの引数を省略可能としており、 省略された場合暗示イベントループを意味するとしています >>1
手順群
手順群の系列。
文脈
要素閲覧文脈環境設定群オブジェクトのいずれか。 あるいはスクリプトが指定された場合、その設定群オブジェクト >>1タスクをキューに追加の呼び出し元を意味しています。 (クライアントメッセージキューの場合は、クライアントメッセージキュー関連設定群オブジェクト >>94。)
文書
文書仕様書はこの引数を省略可能としており、 省略された場合にイベントループ文脈についての暗示文書を意味するとしています >>1
fetch
fetch または nullfetch からタスクをキューに追加する場合には、 その fetch実現値となります。既定値は null
捨てる処理
handle fetchInstall で指定されます。

[38] タスクをキューに追加する処理は、 次のようにします。

  1. [14] 文脈環境設定群オブジェクトで、 文脈大域オブジェクトWorkerGlobalScope で、 文脈大域オブジェクト閉じ中なら、
    1. [68] ここで停止します。 >>10
  2. [39] タスクを、 新しいタスクに設定します。
    [40] タスク
    手順群
    手順群 >>1
    >>1
    文書
    文書 >>1
    triggered by user activation その他のフラグ群
    イベントループ現在走っているタスクnull でなければ、 イベントループ現在走っているタスクtriggered by user activation その他のフラグ群
    fetch
    fetch
    順序
    イベントループ内でタスクをキューに追加の実行順序を表す値
    捨てる処理
    捨てる処理
  3. [13] タスクキューを、 イベントループタスクキュー群タスクキューのうちに関連付けられものに設定します。 >>1
  4. [41] タスクキューに、 タスク末尾に追加します。 >>1

[42] タスクを要素キューに (つい) () (queue an element task) する処理は、 タスク源要素要素手順群手順群について、 次のようにします。 >>1

  1. [125] 文書を、 要素節点文書に設定します。
  2. [126] イベントループを、 要素節点文書関連realmagentイベントループに設定します。
  3. [127] イベントループ文書手順群について、 タスクをキューに追加します。

[35] タスクをキューに追加タスクを要素キューに追加する操作は、 色々な処理から呼び出されます。 Webプラットフォームアルゴリズムの基本的な操作の1つです。

[92] 移動の項も参照。

[105] マイクロタスクをキューに入れるは、 名前が似ていますが別の処理です。


[106] 暗示イベントループ (implied event loop) は、 タスクをキューに追加マイクロタスクをキューに追加する処理を呼び出すアルゴリズムから決まるイベントループです。 >>1 仕様書は多くの箇所でイベントループを明示せず、 暗示イベントループに頼る形としています。 (歴史的理由ですが、煩雑さを避けるためもあるのでしょう。)

[107] ほとんどの場合は関係するエージェントが1つだけで、 したがってイベントループも1つに定まるので曖昧ではないのですが、 エージェント間の通信に関する場合は明示しなければならないとされています。 >>1

[108] イベントループ文脈暗示文書 (implied document) は、 次のものです。 >>1

  1. [109] イベントループwindow event loopない場合、
    1. [110] null を返します。
  2. [111] それ以外で、文脈要素の場合、
    1. [112] 文脈節点文書を返します。
  3. [113] それ以外で、文脈閲覧文脈の場合、
    1. [114] 文脈活性文書を返します。
  4. [115] それ以外で、 文脈スクリプトの場合、
    1. [116] 文脈設定群オブジェクト有責文書を返します。
  5. [117] それ以外の場合、
    1. [118] ... はないとされます。

存在

[28] EventSource, MessagePortごみ収集のタイミングは、 タスクタスク・キューに残っているかによって決まります。

[29] これはタスクから EventSource, MessagePort強い参照があると解釈できるかもしれません。
[30] XHR は逆にごみ収集によってタスクを破棄します。

[8] the embed element setup steps は、 同要素に関するタスクが他に追加されている場合、何も実行しません。 (実行中かどうかではなく追加されたかどうかの検査です。) この検査は自タスクのみならず、そこから追加された他のタスクキューからも行われます。

取得

[15] タスクキューFIFO っぽいもので、基本的には最古のものから取得 (実行)、 削除されます。しかし条件を満たさないタスクイベントループに無視されることになっていますから、 厳密には FIFO とは言えません。

[20] イベントループについてタスクキューからタスクを選択するには、 次のようにします。

  1. [70] タスクキューを、 イベントループタスクキュー群内のタスクキューのうち、 いずれか1つでもタスク走らせられるものを、 実装依存の方法で選択した結果に設定します。 >>9
  2. [66] タスクキューnull の場合、
    1. [89] null を返します。
  3. [91] それ以外の場合、
    1. [90] タスクを、 タスクキュータスクのうち、最初の走らせられるものに設定します。
    2. [64] タスクキューから、タスク削除します。
    3. [67] タスクを返します。

[21] 同じタスクキュータスクは、無視 (遅延) されるものを除き、 実行順序が保証されています。異なるタスクキュータスク同士がどの順序で実行されるかは、 実装依存です。

[69] この辺の処理は、プラットフォームの影響を受けることもあるでしょうし、 あるいは何を優先的に実行するかは実装の品質の問題であって (>>12) Webブラウザー事業者が工夫して競合するべき点でもあるでしょうから、 仕様としてはあまり具体的に規定せず、かなり自由度を持たせているようです。 何をどのような順序で処理するかが相互運用性にあまり影響しないということもあります。

[79] WebSocketメッセージ受信におけるタスクの実行では、 タスクの実行に必要な I/O 処理を待つ間他のタスクキューを実行するような効率化が推奨されています。

[48] かつては、 タスクの決定時点ではまだタスクキューから削除せず、 イベントループによるタスクの実行後にタスクキューから削除すると規定されていた時期もありました。 仕様書の構成上の違いだけで、観測可能な違いは生じないはずで、 Webブラウザーは好きな方法で実装できます。

[47] タスク走らせられるときしか選ばれません。 その条件には文書完全に活性か否かが含まれます。 従って、履歴移動により非表示状態になった文書タスクは、 実行されません。しかし捨てられたわけではないので、再び表示状態に戻れば実行されます。

[34] ポートメッセージキュークライアントメッセージキューは、 有効か無効かのいずれかの状態を持ちます。 既定値は無効です。


[80] HTML構文解析器script 要素終了タグの処理は、 字句化器をブロック (block the tokenizer) する場合があります。これは、 字句化器をブロック解除 (unblock the tokenizer) するまでの間、 当該字句化器を実行することになるタスクイベントループが実行しないものと説明されています >>78

[71] なぜかこれは構文解析器の動作の規定で説明されるだけで、 イベントループ側のアルゴリズムには組み込まれていません。 そのため仕様書の意図する正確な動作は不明です。 しかし、構文解析器自体が正常に動作することや他の挙動との整合性、 実際の Webブラウザーの動作との一貫性を考慮すると、 イベントループが単一のタスクキューしか持たない場合であってもそのようなタスクの後に続く一切のタスクを実行できないとは考えにくく、 完全に活性でないタスクと同様、ブロック解除されるまで無効とされると解釈するのが妥当そうです。

[82] なお、このような挙動を引き起こしたHTML構文解析器によってブロックされる、 字句化器を実行することになるタスク、というのは、 navigate によって実行される fetchprocess responseprocess response end-of-body の処理を行うネットワークタスク源タスクです。

[81] ということは、字句化器をブロックするとは、 (タスク源 = ネットワークタスク源, 文書 = HTML構文解析器文書, fetch = その構文解析器と対になる fetch) のタスクキュー部分リスト状態無効に設定する、と言い換えられることになります。

削除

[22] タスクは実行される際にキューから削除されますが、それ以外にも削除されることがあります。

移動

ポートメッセージキュー

[17] ポートメッセージキューにおいては、 タスクが他のポートメッセージキューへと移動されることがあります。 タスクキュー部分リスト内のすべてのタスクを削除し、 他のポートメッセージキューに改めて追加するものと解することができます。

[36] ポートメッセージキューの操作 (postMessageTransfer) でタスクポートメッセージキューに追加されることがあります。 仕様書上はタスクをキューに追加を使わずに規定されていますが、 ポートメッセージキュータスクキュー部分リストであると考えれば、 タスクをキューに追加する操作で記述できます。

[73] ポート出荷に伴うタスク移動: ポートメッセージキュータスクは、MessagePort既に出荷済みフラグがである間、 未出荷済みポートメッセージキューに属するものとみなされ、 ポートメッセージキューとしての処理は停止されると規定されています。 これは (色々な実装方法がありそうですが) 未出荷済みポートメッセージキューを収容するタスクキューからポートメッセージキューに相当するタスクキュー部分リストを削除し、 ポートメッセージキューが本来収容されるべきタスクキューに追加する操作と解することができます。 この操作ではタスク自体は削除と移動されるわけではなく、 タスクキュー上のタスク順序が維持される必要があります。

サービスワーカー

[93] サービスワーカーを走らせる処理、 サービスワーカーを終端させる処理で、 イベントループサービスワーカー登録との間でタスクが移動されることがあります。

[77] handle fetchタスクが捨てられる時は、 タスク捨てる処理が実行されます。

イベント順との関係

[55] DOM3イベントイベント同士の関係をイベント順により規定しています。 DOM3イベントイベント・ループタスクという概念を使っておらず、 このイベント順は適宜タスク源として使うことによってイベント・ループと互換性がある形で実装できる、 としています。

[57] 具体的にどう対応付けるのかは説明を読んでもあんまりよくわかりません。 HTMLマウス鍵盤も同じ利用者対話タスク源で扱っていますが、 DOM3イベントは独立してるからそれぞれ別のタスク源だ、とか言っていますし、 焦点の変更など独立した操作がそれぞれタスク源だ、とか訳のわからないことも言ってます。

ごみ収集との関係

[74] ごみ収集ポートメッセージキュー参照。

歴史

[95] Clarify realm and task-queuing situation in pipeTo() by domenic · Pull Request #902 · whatwg/streams () https://github.com/whatwg/streams/pull/902

[96] Add self.queueMicrotask() (domenic著, ) https://github.com/whatwg/html/commit/9d7cf125f960e6bb8d9b7c9456595f505f2e9d4b

[97] document.open() simplifications, part 1 (TimothyGu著, ) https://github.com/whatwg/html/commit/6f769b8089a843066aa19f5991405bf4c84458b3

[98] No longer remove tasks for document.open() by annevk · Pull Request #3665 · whatwg/html () https://github.com/whatwg/html/pull/3665

[99] document.open() simplifications: realm creation, unloading, tasks removal by TimothyGu · Pull Request #3918 · whatwg/html () https://github.com/whatwg/html/pull/3918

[100] document.open() simplifications, part 2 (TimothyGu著, ) https://github.com/whatwg/html/commit/ae7cf0cc1936c6c309d7279c822dffc3af147851

[101] Editorial: rigorize tasks and task queuing (domenic, , ) https://github.com/whatwg/html/commit/f4e29076caad1779336adea40ac2125d6d1c9496

[119] Script event-loop: ignoring tasks for documents that are not fully active · Issue #4242 · whatwg/html () https://github.com/whatwg/html/issues/4242

[120] Editorial: rigorize tasks and task queuing by domenic · Pull Request #4465 · whatwg/html () https://github.com/whatwg/html/pull/4465

[121] Editorial: remove now-redundant removal of event loop task (domenic, , ) https://github.com/whatwg/html/commit/edcf2eff7570fd142188e45350eb9c69bad9b9fc

[122] Editorial: remove now-redundant removal of event loop task by domenic · Pull Request #4897 · whatwg/html () https://github.com/whatwg/html/pull/4897

[123] Duplicated removal from queue in the Event Processing Model · Issue #4888 · whatwg/html () https://github.com/whatwg/html/issues/4888

[124] Add "queue an element task" algorithm (dtapuska, , ) https://github.com/whatwg/html/commit/a9e1d2ad5a7569010c685b271965ae4a3a34a64b

[128] Add the ability to queue an element task. by dtapuska · Pull Request #5072 · whatwg/html () https://github.com/whatwg/html/pull/5072