[2] タスクキューは、イベントループにおけるタスクの順序付きのリスト (キュー) です。 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つ以上のタスクキュー群を持ちます。 これは活性ワーカーが動作していない間にタスクを保持しておくもので、 これ自体を使ってタスクを実行するものではありません。 >>75
[46] 各タスクは、何らかのタスク源から来るものと定義されます >>44。
[102] タスクは、 源を持ちます。 源は、 タスク源のいずれかであって、 関連するタスクを集団化し直列化するために使われます。 >>9
[103] あるイベントループにおいてあるタスク源は、 当該イベントループの特定のタスクキューと関連付けられなければなりません >>9。 この関係はイベントループが開始された時から終了する時まで変わることがありません。
[104] いわばタスク源はタスクキューのラベルのような働きを持っています。 タスク源には1つタスクキューがありますが、 タスクキューのタスク源は1つとは限りません。 複数のタスク源が同じタスクキューを共有することがあります。 すべてのタスク源が独立したタスクキューを持つ状態が、 タスクキューを最大限分割した状態といえます。
[61] タスクキューはタスク源によって分けられており、 同じタスク源のタスク同士の実行順序はタスクキューへの追加順序となることが保証されます。
[62] タスク源は、追加時にタスクキューの決定に使われる他、 何らかの理由でタスクキューからタスクを削除する条件として使われることもあります。
[50] ほとんどのタスク源はイベントループに1つずつ存在していますが、
ポートメッセージキューは著者が MessagePort
オブジェクトを作成することによって任意個作成されます。
クライアントメッセージキューは ServiceWorkerContainer
オブジェクトの数だけ存在します。
媒体要素イベントタスク源と
XMLHttpRequest
タスク源 もオブジェクトごとに存在します。
FileReader
タスク源、FileSaver
タスク源もオブジェクトごとに存在するようです。
[51] 未出荷済みポートメッセージキューは仮想タスク源 >>54 であり、そのタスクはポートメッセージキューにも未出荷済みポートメッセージキューにも属するという特殊な状態になっています。 未出荷済みポートメッセージキューはイベントループごとに1つだけあります >>45。
MessagePort
では必ず同じ順序でタスクが実行されることを保証し、
転送してしまった MessagePort
では任意の実行順序となることを認めるためにこのような複雑な構造になっています。[58] マイクロタスクのタスク源はすべてマイクロタスクタスク源と定義されています。
[59] マイクロタスクにはタスクキューとは別のマイクロタスクキューが存在しています。 これはマイクロタスク源のタスク (マイクロタスク) を実行するタスクキューとは別のものです。
[83] 仕様書上、タスクキューはタスクの集合であるとしか説明されていません。 しかし、タスクキュー上のタスクには、源、文書、fetch という情報が関連付けられていて、これがタスクキューが関わる色々な演算で重要な役目を持ちます。
[85] タスクキューは、源、文書、fetch という情報を持ったタスクのキューであるが、 通常のキューとは異なる特殊な演算も持つ、と解釈することもできますし、 源、文書、fetch をキーとするタスクのリスト (タスクキュー部分リスト) をいくつか重ね合わせて全体として順序を持つリストとして捉えたものがタスクキューである、 と解釈することもできそうです。
[86] ポートメッセージキューやクライアントメッセージキューは、タスクキュー部分リストの一種であると解せます。
[87] 未出荷済みポートメッセージキューは、いくつかのポートメッセージキューを束ねたものと捉えることができます。 ただし、未出荷済みポートメッセージキューのタスクと各ポートメッセージキューのタスクが異なるタスクキューを利用する場合を考えると、 事情は若干複雑化します。
[65] タスクキュー部分リストは、状態を持ちます (>>66)。
[11] タスクをキューに追加する処理 >>1 は、新たにタスクの実行を予定するものです。
[43] タスクは、その処理に関係するイベントループに追加されます。 Webブラウザーが複数のイベントループを持つ場合、 処理対象の文書やワーカーを担当しているイベントループのタスクキューに追加されることになります。
[3] タスクは、その出自であるタスク源によって決まるタスクキューに追加されます。 イベントループが複数のタスクキューを持つ場合、 同じタスク源からのタスクは必ず同じタスクキューに追加され、 相互の順序は保持されますが、 異なるタスク源からのタスクは異なるタスクキューに追加されるかもしれないため、 順序は保証されません。
[37] タスクをキューに追加する処理は、 次の引数を受け取ります。
[38] タスクをキューに追加する処理は、 次のようにします。
[42] タスクを要素キューに追加する処理は、 タスク源源、 要素要素、 手順群手順群について、 次のようにします。 >>1
[35] タスクをキューに追加やタスクを要素キューに追加する操作は、 色々な処理から呼び出されます。 Webプラットフォームのアルゴリズムの基本的な操作の1つです。
[92] 移動の項も参照。
[105] マイクロタスクをキューに入れるは、 名前が似ていますが別の処理です。
[106] 暗示イベントループは、 タスクをキューに追加やマイクロタスクをキューに追加する処理を呼び出すアルゴリズムから決まるイベントループです。 >>1 仕様書は多くの箇所でイベントループを明示せず、 暗示イベントループに頼る形としています。 (歴史的理由ですが、煩雑さを避けるためもあるのでしょう。)
[107] ほとんどの場合は関係するエージェントが1つだけで、 したがってイベントループも1つに定まるので曖昧ではないのですが、 エージェント間の通信に関する場合は明示しなければならないとされています。 >>1
[108] イベントループと文脈の暗示文書は、 次のものです。 >>1
[28] EventSource
, MessagePort
のごみ収集のタイミングは、
タスクがタスク・キューに残っているかによって決まります。
[8] the embed
element setup steps は、
同要素に関するタスクが他に追加されている場合、何も実行しません。
(実行中かどうかではなく追加されたかどうかの検査です。)
この検査は自タスクのみならず、そこから追加された他のタスクキューからも行われます。
[15] タスクキューは FIFO っぽいもので、基本的には最古のものから取得 (実行)、 削除されます。しかし条件を満たさないタスクはイベントループに無視されることになっていますから、 厳密には FIFO とは言えません。
[20] イベントループについてタスクキューからタスクを選択するには、 次のようにします。
[21] 同じタスクキューのタスクは、無視 (遅延) されるものを除き、 実行順序が保証されています。異なるタスクキューのタスク同士がどの順序で実行されるかは、 実装依存です。
[69] この辺の処理は、プラットフォームの影響を受けることもあるでしょうし、 あるいは何を優先的に実行するかは実装の品質の問題であって (>>12) Webブラウザー事業者が工夫して競合するべき点でもあるでしょうから、 仕様としてはあまり具体的に規定せず、かなり自由度を持たせているようです。 何をどのような順序で処理するかが相互運用性にあまり影響しないということもあります。
[48] かつては、 タスクの決定時点ではまだタスクキューから削除せず、 イベントループによるタスクの実行後にタスクキューから削除すると規定されていた時期もありました。 仕様書の構成上の違いだけで、観測可能な違いは生じないはずで、 Webブラウザーは好きな方法で実装できます。
[47] タスクは走らせられるときしか選ばれません。 その条件には文書が完全に活性か否かが含まれます。 従って、履歴移動により非表示状態になった文書のタスクは、 実行されません。しかし捨てられたわけではないので、再び表示状態に戻れば実行されます。
[34] ポートメッセージキューとクライアントメッセージキューは、 有効か無効かのいずれかの状態を持ちます。 既定値は無効です。
[80] HTML構文解析器の script
要素の終了タグの処理は、
字句化器をブロックする場合があります。これは、
字句化器をブロック解除するまでの間、
当該字句化器を実行することになるタスクをイベントループが実行しないものと説明されています
>>78。
[71] なぜかこれは構文解析器の動作の規定で説明されるだけで、 イベントループ側のアルゴリズムには組み込まれていません。 そのため仕様書の意図する正確な動作は不明です。 しかし、構文解析器自体が正常に動作することや他の挙動との整合性、 実際の Webブラウザーの動作との一貫性を考慮すると、 イベントループが単一のタスクキューしか持たない場合であってもそのようなタスクの後に続く一切のタスクを実行できないとは考えにくく、 完全に活性でないタスクと同様、ブロック解除されるまで無効とされると解釈するのが妥当そうです。
[82] なお、このような挙動を引き起こしたHTML構文解析器によってブロックされる、 字句化器を実行することになるタスク、というのは、 navigate によって実行される fetch の process response や process response end-of-body の処理を行うネットワークタスク源のタスクです。
[81] ということは、字句化器をブロックするとは、 (タスク源 = ネットワークタスク源, 文書 = HTML構文解析器の文書, fetch = その構文解析器と対になる fetch) のタスクキュー部分リストの状態を無効に設定する、と言い換えられることになります。
[17] ポートメッセージキューにおいては、 タスクが他のポートメッセージキューへと移動されることがあります。 タスクキュー部分リスト内のすべてのタスクを削除し、 他のポートメッセージキューに改めて追加するものと解することができます。
[36] ポートメッセージキューの操作
(postMessage
や Transfer) でタスクがポートメッセージキューに追加されることがあります。
仕様書上はタスクをキューに追加を使わずに規定されていますが、
ポートメッセージキューがタスクキュー部分リストであると考えれば、
タスクをキューに追加する操作で記述できます。
[73] ポート出荷に伴うタスク移動:
ポートメッセージキューのタスクは、MessagePort
の既に出荷済みフラグが偽である間、
未出荷済みポートメッセージキューに属するものとみなされ、
ポートメッセージキューとしての処理は停止されると規定されています。
これは (色々な実装方法がありそうですが)
未出荷済みポートメッセージキューを収容するタスクキューからポートメッセージキューに相当するタスクキュー部分リストを削除し、
ポートメッセージキューが本来収容されるべきタスクキューに追加する操作と解することができます。
この操作ではタスク自体は削除と移動されるわけではなく、
タスクキュー上のタスクの順序が維持される必要があります。
[93] サービスワーカーを走らせる処理、 サービスワーカーを終端させる処理で、 イベントループとサービスワーカー登録との間でタスクが移動されることがあります。
[77] handle fetch のタスクが捨てられる時は、 タスクの捨てる処理が実行されます。
[55] DOM3イベントはイベント同士の関係をイベント順により規定しています。 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