[3] Webブラウザーにおけるイベント、fetch、構文解析、スクリプト実行、 レンダリングその他の動作の相互作用は、 イベントループによって説明されています。
[15] 非同期システム、 GUI システムの同様の概念に倣ってイベントループと呼ばれていますが、 実際に Webブラウザーで実行される処理の単位はイベントではなく、タスクと呼ばれています。 JavaScript で利用される DOM のイベントはタスクであることもあれば、タスクの処理の一部分であることもあります。
[207] 1つのWebブラウザー上では、複数の Webサイトなどが同時にレンダリング・動作しています。単一のWebページも、閲覧文脈本体の他、複数のワーカーが並行して動作することがあります。そのためイベントループも同時に複数存在することがあります。
[6] 利用者エージェントは、イベント、利用者との対話、スクリプト、 レンダリング、ネットワーク処理、その他の協調のためにイベントループを使わなければなりません。 イベントループは利用者エージェント毎に少なくても1つなければなりません。 関係する類似起源閲覧文脈の単位毎に高々1つのイベントループを有することができます。 >>5
document.domain
を考慮した)
起源ごとのグループを分離してはいけない、ということです。[11] イベントループのすべての閲覧文脈が捨てられる時、イベントループ自体も捨てられます。 逆に閲覧文脈は1つイベントループを持ちます。
[91] ワーカーのイベントループは閲覧文脈ではなく、ワーカーに関連付けられています。 ワーカーが閉じられた時にイベントループも捨てられます。
[93] サービスワーカーを走らせる処理でもイベントループが作られます。
[71] 「要素のイベントループ」は明確に定義されていませんが要素の節点文書が属する閲覧文脈が属するイベントループを指すようです。
[161] イベントループが実行する処理の単位はタスクと呼ばれます。
特定のイベントループが同時に実行するタスクは高々1つであり、
現在走っているタスクと呼ばれます。
現在走っているタスクの初期値は null
です。 >>5
[217] スクリプトを走らせる準備は現在走っているタスクを参照しています。
[13] メインやワーカーのイベントループイベントループは、 次のようにしなければなりません >>5。
[53] イベントループの手順中でタスクとマイクロタスクの実行では著者によるスクリプトが実行される可能性があります。 またレンダリングの更新でもアニメーションフレームコールバックなどとして著者によるスクリプトが実行されることがあります。
[130] アイドル状態になったと判定すると、 requestIdleCallback
のコールバック関数の実行のためのタスクをキューに追加することになっています。
[75] イベントループのタスクの処理は、次のようにします。
[182] かつてはタスクの実行後にストレージミューテックスの解放も行うこととされていました。
[183]
かつてはタスクを実行した後でタスクキューから削除すると規定されていました。
[48] 次に示すものは、「最後にイベントループの手順1に到達した時」 の状態を定義に含めています。
[158] 次に示すものは、「次にイベントループの手順1に到達する前」を定義に含めています。
[68] また、次に示すものは、同じタスク内であれば同じ結果になることが求められています。
[66] これらは、次の event loop level 1 に到達する前に実装が保持する値を更新したり、 新たな状態を反映させるための処理を行ったりする必要があります。
[135] イベントループのレンダリングの更新の各処理とレンダリングの更新の計測の間に、 次のようにします >>5。
[70] requestIdleCallback
のアイドル期間の決定では、
レンダリングその他の内部処理のスケジューリングが影響を及ぼします。
[212] イベントループをスピンは、 一種の継続で、一旦現在の処理を中断してイベントループに制御を戻し、 指定した条件条件が達成された後に再開するものです。
[17] イベントループイベントループのスピンは、 次のようにしなければなりません >>5。
[168] かつては global script clean-up jobs の実行もここで行われていました。
[19] 並列に、条件が成立するのを待ちます。 成立したら、次のようにしなければなりません。 >>5
[25] document.close
はスピンするまで字句化を行います。
document.close
参照。[205] かつては >>160、媒体要素が文書から削除された後、次にイベントループがスピンするより前に再度挿入されない場合、 ハードウェア資源に制約があればその機会にこれをすべて解放するのがよいとされていました >>159。
script
要素の終了タグの処理showModalDialog
(ダイアログが閉じられるの待ち)[125] stops parsing におけるスピンは、スピンを使わない形に読み替えられます。
[231] script
要素の終了タグの処理の場合、
スピンの直前に同じ構文解析器に処理させるタスクの実行をブロックし、
直後にブロック解除することになっています。
従って、既に fetch が続きの部分の構文解析を求めるタスクを追加していたとしても、
スピンの時点で保留タスクとなって、
スピンの条件達成により追加される継続タスクが先に実行されることになります。
[172] HTML Standard では >>17 の通りタスクの実行を中断して条件が成立してから再開する形を採っていますが、 実際の Webブラウザーでは JavaScriptエンジンの仕様上そのように中断させることは難しく、 イベントループ自体を再帰的に実行しているようです。
[59] script
要素の処理でスピンする場合、その直前に HTML
字句化器やXML構文解析器がブロックされ、直後にブロックが解除されます。
これにより、スピン中に当該字句化器・構文解析器を使うようなタスクは実行されない、
とされています。
[152] HTML字句化器や XML構文解析器を使うタスクというのは、どうやら実際には、
HTML や XML のファイルを fetch した結果としてバイト列を受信する度に追加されるタスクのことを指しているようです。
つまりブロックされている間はそれ以上先に字句化が進まないという規定であるわけです。
文書に関連付けられたHTML構文解析器やXML構文解析器が利用されるのは、文書自体の構文解析を除けば、
HTML文書における document.write
/document.writeln
の呼び出しだけのようです。
そちらは定義上、字句化器がブロックされるのと同じ条件下で HTML構文解析器を呼び出さないことになっています。
(なのでいずれにせよ字句化器は止まって先に進みません。)
[26] ある条件が満たされるまで利用者エージェントを一時停止する場合、
次のようにしなければなりません。 >>5
[127] 一時停止中のレンダリングについては、モーダルダイアログも参照。
[223] 一時停止中でも動画の再生やアニメーションは続行するべきかもしれません。
[220] pause 中は他のタスクを実行できないというのが仕様上の規定ですが、 Firefox ではモーダルダイアログの表示中に Bookmarklet を実行できる (つまり navigate からスクリプト実行のタスクが実行される) ようです。
[243] 同じイベントループを共有しているなら、他のタブや窓であっても、 タスクは実行できなくなります。
[221] 1つの利用者エージェントが複数のイベントループを使う場合、 あるイベントループが一時停止中でも、他のイベントループは動作するかもしれません。
[237] HTML Standard は、2016年5月以来、Web互換性に悪影響を及ぼさない限りにできるだけこの“異常”な挙動を除去できないか試みることを Webブラウザーの実装者に呼びかけています >>5。
[218] ワーカーは、一時中断されることがあります。 イベントループの実行も中断されるようです。
[102] 利用者の指示により、またはバッテリーの都合により睡眠状態に入ったなどの理由で、 プラットフォームが強制的に Webブラウザーの動作を中断させたり、 そこから復帰させたりすることがあります。これを Webブラウザーが検知できるかは、 プラットフォーム次第です。しかし検知できるか否かに関わらず、 時刻やタイマーの処理などで不整合が生じないように配慮が必要です。
[108] イベントループは、存在する間動作する HTML Standard (つまり存在しなくなったら停止する) とされています。
[129] 文書環境のイベントループについては、 関係する閲覧文脈がすべて破棄された時、 ということになると思われます。
[131] ワーカー環境についてはより明確に規定されています。
イベントループのタスクキュー群のタスクがなくなり、
イベントループの WorkerGlobalScope
の閉じ中フラグが真の場合
HTML Standard、破棄されます。
(その後ワーカーを走らせる手順の最終段階へと進みます。)
[286] イベントループは変数タスク開始時刻により経過時間を保持しています。
[250] タスク開始時刻とタスクと今についてタスクの時間長を報告するには、 次のようにします。 >>5
[255] この手順は、タスクとその直後のマイクロタスクの実行 (>>74) の後に呼び出されます。
[257] イベントループと文書群と今についてレンダリングの更新の時間長を報告するには、 次のようにします。 >>5
[258] この手順は、レンダリングの更新の実行後に呼び出されます。
[61] HTML の構文解析器 (や、ちゃんと規定した仕様書が存在していませんが、 XML の構文解析器) は、それ自体はタスクの一部や全部ではなく、イベントループとは概念として独立しています。
[62] innerHTML
のように完全にタスクに含まれる処理の一部分として構文解析が実行されることもあれば、
fetch によってネットワークからデータを取得する度に順次生成されていく一連のタスクによって断続的に構文解析が進められることもあります。
[149] >>24 や >>59 の通り、構文解析によってイベントループがスピンしたり、字句化器がブロックされたりすることがあります。
[201] スクリプトは他のスクリプトが実行されていることを直接観測できません >>200。
実装上は複数のスクリプトが並列実行されている可能性はありますが (起源が異なる場合やワーカーなど)、
そのようなスクリプト同士が通信する方法は postMessage
など限られています。
[203] これによって著者はスレッド間のアクセス制御など複雑な処理を書かなくても済みます。 Webブラウザーはスクリプトが同時実行されないことを前提とした最適化を行えます (がそれが制約となるケースもあるかもしれません)。
[43] いくつかのアルゴリズムは並列実行されます。すなわち、 イベントループの動作中に同時に他のアルゴリズムが実行されていることがあります。
[46] HTML 以前に規定されたものや、 HTML 以後であっても明確な仕様が存在しないものは、 イベント・ループとどう相互作用するのか文書化されていません。
[45] XSLT の処理とイベント・ループの関係は定義されていません。 >>44
[145] Geolocation API はイベントループが定義される前の仕様書なので関係が説明されていません。おそらく
getCurrentPosition
や watchPosition
のアルゴリズムは非同期的に実行されますwatchPosition
は非同期的に実行されているアルゴリズムを停止させます[67] video
や audio
の再生の具体的なタイミングは規定されていません。
なお track
のレンダリングは媒体要素のレンダリングに合わせて更新しなければならないと規定されています。
[95] いくつかの算法の一部分は原子的に実行するよう規定されています。
[79] 仕様書の規定するイベントループを実際にどのような形で実装するべきかは、 仕様書の範囲外となっています。他のアルゴリズム同様、 著者のスクリプトから観察してブラックボックスとして等しい結果が得られる限り、 どのような方法で実装しても問題ありません。
[84] 各イベントループは、それぞれがプラットフォームの別のプロセスとして動作するかもしれませんし、 同じプロセスの異なるスレッドで動作するかもしれません。
[82] Webブラウザーは仕様書で規定される処理の他にも、 利用者インターフェイスの処理やプラットフォームとのやり取りなど、 Webページの相互運用性には関わらない様々な処理が必要になります。 Webブラウザーの実装手法としての“イベントループ”と、 仕様上の (= 著者のスクリプトから見た) イベントループは必ずしも一致しません。
[54] window.length
は同じイベントループで動作しているかどうかによって挙動が変わり得ます。
[128] 最上位閲覧文脈はそれぞれセッション履歴イベントループを持ちます。 セッション履歴イベントループはメインやワーカーのイベントループとは異なり履歴管理専用で、とても単純になっています。
[4] イベント・ループの概念は Web Applications 1.0 (HTML Living Standard) によってはじめて体系的に説明、仕様化されました。
[87] イベント・ループは最初に Web Workers においてワーカーの挙動を説明するために導入されました。
[89] 更にその後、メイン・スレッドについてもイベント・ループが定義されるようになりました。 タスクの概念もこの時導入されました。
[86] ワーカーのイベント・ループはメインのイベント・ループと同じように処理されますが、 >>87、>>89 という経緯からか当初は run a worker 算法に組み込まれており、 閉じ中フラグの存在など微妙に定義が違っていました。 しかし >>85 によって両者の定義が統合されました。
[137] セッション履歴イベントループはイベントループが複数ある環境での履歴操作を記述するために2013年9月に導入されました。
[106] Web Applications 1.0 r7980 Lay the groundwork for DOM Core to handle reentrant mutation observers. ( ( 版)) http://html5.org/tools/web-apps-tracker?from=7979&to=7980
[109] IRC logs: freenode / #whatwg / 20130701 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20130701#l-216
[110] Bug 22522 – WebIDL, error handling, and promises ( ( 版)) https://www.w3.org/Bugs/Public/show_bug.cgi?id=22522
[111] IRC logs: freenode / #whatwg / 20130701 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20130701#l-619
[126] IRC logs: freenode / #whatwg / 20130924 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20130924
[143] IRC logs: freenode / #whatwg / 20131026 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20131026
[144] IRC logs: freenode / #whatwg / 20131030 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20131030#l-662
[156] IRC logs: freenode / #whatwg / 20140204 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20140204
[157] Add a warning sign for synchronous usage of the XMLHttpRequest API · 575999a · whatwg/xhr ( ( 版)) https://github.com/whatwg/xhr/commit/575999ae46afadc8f2ac6376c68fa7a887a88aa6
[160] Web Applications 1.0 r8510 Lay the groundwork for interruptible microtasks, mutation-observer style. ( 版) http://html5.org/tools/web-apps-tracker?from=8509&to=8510
[175] Web Applications 1.0 r8553 Make microtasks work in workers too, since eventually we'll want the JavaScript stuff to hook into this ( 版) http://html5.org/tools/web-apps-tracker?from=8552&to=8553
[176] >>175 でワーカーにもマイクロタスクが導入されました。
[215] Web Applications 1.0 r8832 Hyperlink to 'step 1' of the event loop ( ( 版)) https://html5.org/r/8832
[216] IRC logs: freenode / #whatwg / 20141119 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20141119#l-819
[52] 2014年11月には、レンダリングの更新処理とイベントループとの関係が明確化されました。
[1] Timing and Synchronization in JavaScript - Opera Developer Community ( 版) http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/
[77] Web Applications 1.0 r2074 Define event loops, task queues, etc; Make 'fetching' use this mechanism (everything will in due course); Fix some cross-references around 'interactive content'. ( 版) https://html5.org/r/2074
# [17:24] <annevk> ek_: it doesn't necessarily have to be a distinct thread, but you have to be pretty clever to pull that of (Opera used to do that)
[113] BlinkOn Scheduler Talk - Google スライド ( 版) https://docs.google.com/presentation/d/1vqqBwDbnwrCz0P5JX_fxVQd0Q5KmVZdB_hk6RLNgO2Q/edit
[219] Surfin' Safari - Blog Archive » Introducing the Rendering Frames Timeline ( 版) https://www.webkit.org/blog/3996/introducing-the-rendering-frames-timeline/
[224] IRC logs: freenode / #whatwg / 20151118 ( 版) http://krijnhoetmer.nl/irc-logs/whatwg/20151118
[226] Remove the storage mutex due to lack of implementation · whatwg/html@1b918cf ( 版) https://github.com/whatwg/html/commit/1b918cf72fcbba011f83b92ab5d1f483fb1cafa3
showModalDialog
の廃止[227] Remove showModalDialog() · whatwg/html@eec9646 ( 版) https://github.com/whatwg/html/commit/eec96462b5bd1c7f904a4880bc04dade6efcd597
[114] イベントループとは直接関係ありませんが、利用者インターフェイスが無効化されることがあります。
[115] showModalDialog
によるモーダルダイアログの表示中は、その呼び出し元と同じ起源の閲覧文脈
(正確には「背景閲覧文脈のリストに含まれる閲覧文脈」) の利用者インターフェイスを無効化しなければなりません
http://www.whatwg.org/specs/web-apps/current-work/#dom-showmodaldialog。
[116] これはすなわち http://www.whatwg.org/specs/web-apps/current-work/#dom-showmodaldialog、
[123] ということで、一時停止と似ていますが、同期区間などを実行しないこと、 利用者からのイベントを無視することが違っています。
[146] inert も類似した状況を作り出します。 inert は inert
属性やdialog
要素によって発生します。
[228] Integrate with the ES job queue · whatwg/html@12db63c ( 版) https://github.com/whatwg/html/commit/12db63c7c038b9d8f1d3501d6661d89d495abeac
[229] Rewrite script execution on top of ES · whatwg/html@4891d18 ( 版) https://github.com/whatwg/html/commit/4891d18aaf2df1d40aa61f467a5a10cfc19dd85d
[241] Editorial: make wait a concept for bodies instead of responses · whatwg/fetch@1873eda ( 版) https://github.com/whatwg/fetch/commit/1873edac285df87c495b1966d8fdb2fd7ba733b2
[242] Allow for a request to finish after a response starts to arrive · whatwg/fetch@3a41b6f ( 版) https://github.com/whatwg/fetch/commit/3a41b6f04996d4aac13ecad5b38635827dcd0df3
[236] Add a warning about the "pause" operation ( (domenic著, )) https://github.com/whatwg/html/commit/8d564d1b5589906f77589b499e1ebf44671d2ee6
[78] Remove global script clean-up jobs (mkruisselbrink著, ) https://github.com/whatwg/html/commit/305aa6705e2ae65ae8a407c53316359dfe286eba
[94] [worklets] Clarify that the event loop is not run continuously. (bfgeek著, ) https://github.com/w3c/css-houdini-drafts/commit/4b7d4dfaac7acd3ca6c5c5131a2a65874265327d
[96] Do we need to mandate agents and event loops being 1:1? · Issue #2526 · whatwg/html () https://github.com/whatwg/html/issues/2526
[97] Editorial: minor event loop processing model cleanup (annevk著, ) https://github.com/whatwg/html/commit/7ddfd096ba815d4bd4e8b3ff7900bef1e95b985c
[98] atotic/event-loop: event loop docs () https://github.com/atotic/event-loop
[99] Meta: export some event loop-related definitions (domenic著, ) https://github.com/whatwg/html/commit/b0da8d31269485c5ff794912dff354c5d966900b
[100] Meta: export some event loop-related definitions by domenic · Pull Request #2836 · whatwg/html () https://github.com/whatwg/html/pull/2836
[101] Cross-link to update the rendering · Issue #10 · WICG/paint-timing () https://github.com/WICG/paint-timing/issues/10
[103] Clarify that specification text usually starts on the event loop (domenic著, ) https://github.com/whatwg/html/commit/bae35b1a90f723efb1c913438d9e1441fa67461a
[104] "Do any synchronous setup work, while still on the event loop..." · Issue #2800 · whatwg/html () https://github.com/whatwg/html/issues/2800
[105] Clarify that specification text usually starts on the event loop by domenic · Pull Request #2803 · whatwg/html () https://github.com/whatwg/html/pull/2803
[107] Allow UAs to conditionally block on stylesheet loading (domfarolino著, ) https://github.com/whatwg/html/commit/42dd707cbfc0f5d8f88b04ef270f4fcb121a10ff
[132] Integrate with requestIdleCallback (rmcilroy著, ) https://github.com/whatwg/html/commit/01787ee712a7803e64e0da6ac9644a5e6b8d2cca
[154] Missing definition for "idle time" · Issue #70 · w3c/requestidlecallback () https://github.com/w3c/requestidlecallback/issues/70
[155] Hook into HTML spec. by rmcilroy · Pull Request #75 · w3c/requestidlecallback () https://github.com/w3c/requestidlecallback/pull/75
[174] Integrate with requestIdleCallback by domenic · Pull Request #3570 · whatwg/html () https://github.com/whatwg/html/pull/3570
[177] Integrate with requestIdleCallback by rmcilroy · Pull Request #4104 · whatwg/html () https://github.com/whatwg/html/pull/4104
[178] Fix argument ordering in call to report long tasks (npm1著, ) https://github.com/whatwg/html/commit/9faa107bf28a2a4100203973e41741be1e8e9b77
[185] Arguments ordering in Report long tasks for “user agent does not execute this loop” · Issue #4114 · whatwg/html () https://github.com/whatwg/html/issues/4114
[189] Fix ordering in call to Report long tasks by npm1 · Pull Request #4174 · whatwg/html () https://github.com/whatwg/html/pull/4174
[190] Start an idle period more often (rmcilroy著, ) https://github.com/whatwg/html/commit/4fd4d3df700ecf9d00962fbda760a06014175728
[191] "start an idle period algorithm" not run enough · Issue #4212 · whatwg/html () https://github.com/whatwg/html/issues/4212
[192] Start an idle period if event loop has tasks for non-fully active docs by rmcilroy · Pull Request #4250 · whatwg/html () https://github.com/whatwg/html/pull/4250
[193] Remove parameter from "Report long tasks" call (npm1著, ) https://github.com/whatwg/html/commit/e48c42f60788f318f1d848c33869bb2461673c00
[194] Make fragment loop not depend on spin the event loop (annevk著, ) https://github.com/whatwg/html/commit/e62a7be6f3161993b82e9d8469ba2e64a3c6a2a6
[214] Integrate with the Long Tasks spec (npm1, , ) https://github.com/whatwg/html/commit/425a67ba81288305fce86736a0772f84c3f30eed
[263] Add modifications to HTML from LongTasks Spec by npm1 · Pull Request #4059 · whatwg/html () https://github.com/whatwg/html/pull/4059
[264] Remove parameter from "Report long tasks" call (npm1, , ) https://github.com/whatwg/html/commit/e48c42f60788f318f1d848c33869bb2461673c00
[265] Remove "browser" and "rendering" task types by npm1 · Pull Request #50 · w3c/longtasks () https://github.com/w3c/longtasks/pull/50
[266] Remove param from Report long tasks by npm1 · Pull Request #4186 · whatwg/html () https://github.com/whatwg/html/pull/4186
[267] Editorial: refactor spin the event loop by annevk · Pull Request #4463 · whatwg/html () https://github.com/whatwg/html/pull/4463
[268] Editorial: refactor and explain spin the event loop (annevk, , ) https://github.com/whatwg/html/commit/38c50c4ea111bd8f3ff60d2a49110a62a293c7ac
[271] Editorial: rigorize tasks and task queuing (domenic, , ) https://github.com/whatwg/html/commit/f4e29076caad1779336adea40ac2125d6d1c9496
[273] Script event-loop: ignoring tasks for documents that are not fully active · Issue #4242 · whatwg/html () https://github.com/whatwg/html/issues/4242
[274] Editorial: rigorize tasks and task queuing by domenic · Pull Request #4465 · whatwg/html () https://github.com/whatwg/html/pull/4465
[275] Remove compound microtasks (annevk, , ) https://github.com/whatwg/html/commit/77240a20c840ac60f0b1102ec4ac8be7df717172
[276] Remove compound microtasks by annevk · Pull Request #4437 · whatwg/html () https://github.com/whatwg/html/pull/4437
[277] Editorial: remove now-redundant removal of event loop task (domenic, , ) https://github.com/whatwg/html/commit/edcf2eff7570fd142188e45350eb9c69bad9b9fc
[278] Editorial: remove now-redundant removal of event loop task by domenic · Pull Request #4897 · whatwg/html () https://github.com/whatwg/html/pull/4897
[279] Duplicated removal from queue in the Event Processing Model · Issue #4888 · whatwg/html () https://github.com/whatwg/html/issues/4888
[280] Do not report long tasks outside of the event loop (npm1, , ) https://github.com/whatwg/html/commit/d5a8e4d14d5ab07d3472f7d06077333cefa508b0
[281] Reporting work outside of event loop can cause leaks · Issue #77 · w3c/longtasks () https://github.com/w3c/longtasks/issues/77
[282] Do not report work outside of event loop by npm1 · Pull Request #5123 · whatwg/html () https://github.com/whatwg/html/pull/5123
[285] Editorial: inline event loop start and remove event loop end (npm1, , ) https://github.com/whatwg/html/commit/1ca48214c66aa20fc586773ea9c572e0ef8cab11
[262] Do not report work outside of event loop by npm1 · Pull Request #5123 · whatwg/html () https://github.com/whatwg/html/pull/5123
[287] Remove event loop end by npm1 · Pull Request #5130 · whatwg/html () https://github.com/whatwg/html/pull/5130