[3] [[Webブラウザー]]における[[イベント]]、[[fetch]]、[[構文解析]]、[[スクリプト]]実行、 [[レンダリング]]その他の動作の相互作用は、 [DFN[[RUBYB[[[イベント・ループ]]]@en[event loop]]]]によって説明されています。 [15] 非同期システム、 [[GUI]] システムの同様の概念に倣って[[イベント・ループ]]と呼ばれていますが、 実際に [[Webブラウザー]]で実行される処理の単位は[[イベント]]ではなく、[[タスク]]と呼ばれています。 [[DOM]] の[[イベント]]は[[タスク]]であることもあれば、[[タスク]]の処理の一部分であることもあります。 [96] 本項では[[イベント・ループ]]の他、非同期的な処理の実行や並行的な処理の実行など、 [[Webブラウザー]]における処理のタイミングと関係にまつわる事項全般を扱います。 * 仕様書 [REFS[ - [5] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) ''' - [40] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) ''' - [41] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) ''' - [44] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) ]REFS] * イベント・ループ [6] [[利用者エージェント]]は、[[イベント]]、[[利用者]]との対話、[[スクリプト]]、 [[レンダリング]]、[[ネットワーク]]処理、その他の協調のために[[イベント・ループ]]を使わ[['''なければなりません''']]。 [[イベント・ループ]]は[[利用者エージェント]]毎に少なくても1つ[['''なければなりません''']]。 [[関係する類似起源閲覧文脈の単位]]毎に高々1つの[[イベント・ループ]]を有することができます。 [SRC[>>5]] ;; [8] つまり、[[利用者エージェント]]全体で1つの[[イベント・ループ]]を共有することもできますし、 [[タブ]]毎などの単位で複数の[[イベント・ループ]]に分けることもできるのですが、 その分け方として、 ([CODE(JS)@en[[[document.domain]]]] を考慮した) [[起源]]ごとのグループを分離してはいけない、 ということです。 ;; [9] 仕様上明記されていませんが、おそらくここでいう「[[利用者エージェント]]」の単位は恣意的に決めることができ、 例えば通常モードと秘密モードがあり、両者で開いている [[Web頁]]同士が同じ[[起源]]であっても [[JavaScript]] でアクセスできないなら、これは2つの[[利用者エージェント]]であり、 この規定に違反せずに別々の[[イベント・ループ]]を有することができるはずです。 ;; [7] 1つの[[関連する類似起源閲覧文脈の単位]]に対して複数の[[イベント・ループ]]があると、 そこに属するいずれかの[[閲覧文脈]]が他の[[関連する類似起源閲覧文脈の単位]]に属するような [[navigate]] が発生した時に複雑なことになります。 HTML 仕様はそれをどう処理するか現在定義していません。 [SRC[>>5]] (複雑なこと、というのは具体的には示されていません。) [10] [[イベント・ループ]]は、最低1つ[[閲覧文脈]]を持ちます。 [[イベント・ループ]]のすべての[[閲覧文脈]]が捨てられる時、[[イベント・ループ]]自体も捨てられます。 逆に[[閲覧文脈]]は1つ[[イベント・ループ]]を持ちます。 [SRC[>>5]] [11] [[イベント・ループ]]は1つ以上の[[タスク・キュー]]を持ちます。 [SRC[>>5]] [71] 「[[要素]]の[[イベント・ループ]]」は明確に定義されていませんが[[要素]]の[[文書]]が属する[[閲覧文脈]]が属する[[イベント・ループ]]を指すようです。 ;; 用例: [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-11-16 20:26:18 +09:00]] 版) [42] [[ワーカー]] ([CODE(DOMi)@en[[[WorkerGlobalScope]]]]) は、それぞれ別個の[[イベント・ループ]]を有します [SRC[>>40]]。 ;; [91] [[ワーカー]]の[[イベント・ループ]]は[[閲覧文脈]]ではなく、[[ワーカー]]に関連付けられています。 [[ワーカー]]が閉じられた時に[[イベント・ループ]]も捨てられます。 ** 実行 [13] [[イベント・ループ]]は、それが存在し続ける限り、次の手順を連続的に走らせなければ[['''なりません''']] [SRC[>>5]]。 [FIG[ = いずれかの[[タスク・キュー]]を選んで、そこに[[タスク]]があれば、最古のものを走らせます。 -- ただし、関連付けられた [CODE(DOMi)@en[[[Document]]]] が[[完全に活性]]でないものは無視します。 -- ここで[[利用者エージェント]]は任意の[[タスク・キュー]]を選んで構いません。 = [[イベント・ループ]]が [[storage mutex]] を所有していれば、これを[[解放]]します。 = 最初の段階で[[タスク]]を走らせていれば、それを[[タスク・キュー]]から削除します。 = [[ワーカー]]でないなら: == [[マイクロタスク・チェックポイントを行います]]。 == [[安定状態を提供します]]。 == 必要があれば、任意の [CODE(DOMi)@en[[[Document]]]] や[[閲覧文脈]]の[[レンダリング]]や[[利用者インターフェイス]]を更新して現在の状態を反映させます。 = [[ワーカー]]なら: == [CODE(DOMi)@en[[[WorkerGlobalScope]]]] の[RUBYB[[[閉じ中]]]@en[closing]][[フラグ]]が[[真]]なら、 [[イベント・ループ]]を[RUBYB[破棄]@en[destroy]]して本手順群を停止します。 = [[イベント・ループ]]の最初の手順に戻ります。 ]FIG] ;; [84] [[タスク・キュー]]は[[タスク源]]単位で存在していますから、 同じ[[タスク源]]の[[タスク]]についてはキューに入っている順序で実行されることが保証されますが、 異なる[[タスク源]]の[[タスク]]同士は[[利用者エージェント]]の裁量でどちらを先に実行しても良いことになります。 ;; [14] この辺の処理は、[[利用者エージェント]]が実行される [[OS]] や実装に使っている[[ライブラリー]]等の影響を受けることもあるでしょうし、 あるいは何を優先的に実行するかは[[実装の品質]]の問題であって [[Webブラウザー]]実装者が工夫して競合するべき点でもあるでしょうから、 仕様としてはあまり具体的に規定せず、かなり自由度を持たせているようです。 何をどのような順序で処理するかが[[相互運用性]]にあまり影響しないということもあります。 ;; [16] [[イベント・ループ]]とは別に、[[算法]]の一部分が[[非同期]]的に実行されると規定されているものがあります。 そのような[[算法]]についても、結果を何らかの形で [[DOM]] に反映させる必要があり、 [[イベント・ループ]]が[[安定状態を提供]]することによってそのような[[算法]]の[[同期区間]]が実行される、 あるいは[[タスク・キュー]]に[[タスク]]を追加する、といった形で[[イベント・ループ]]と統合されています。 [[マルチスレッド]]な実装なら[[同期区間]]の前後の[[非同期]]な部分は[[イベント・ループ]]とは別の[[スレッド]]で実装してもよいでしょうし、単一[[スレッド]]なら仕様上の[[イベント・ループ]]を含むより大きな[[イベント・ループ]]の中で交互に処理を行うことになるのでしょう。 [WEAK[(単一[[スレッド]]の [[Webブラウザー]]があるのか知りませんが...)]] ** 手順1到達時点の状態 [48] 次に示すものは、「[RUBYB[最後に[[イベント・ループ]]の手順1に到達した時]@en[last time the event loop reached step 1]]」 の状態を定義に含めています。 [FIG[ - [49] [[スクリプトをブロックしているスタイル・シート]] - [50] [CODE(DOMa)@en[[[ended]]]] [[属性]] ([[媒体要素]]) ]FIG] [56] 次に示すものは、「[RUBYB[最後に[[イベント・ループ]]が[[タスク]]を実行しはじめた時]@en[last time the event loop started executing a task]]」の状態を定義に含めています。 [FIG[ - [57] [CODE(DOMa)@en[[[bufferedAmount]]]] - [58] [[Web Sockets]] の [[garbage collection]] - [65] [CODE(HTMLe)@en[[[embed]]]] [[要素]]の処理 -- [66] [CITE@en[Web Applications 1.0 r7119 Fix to match reality (Firefox in particular) more closely.]] ([TIME[2012-06-06 06:12:00 +09:00]] 版) ]FIG] [68] また、次に示すものは、同じ[[タスク]]内であれば同じ結果になることが求められています。 [FIG[ - [69] [CODE(DOMa)@en[[[canvasResolution]]]] の値や、[[ビットマップ]]作成時に使う[[解像度]] ]FIG] ** スピン [17] ある条件が成立するまで[DFN[[RUBYB[[[イベント・ループをスピン]]]@en[spin the event loop]]]]するという時、 次のようにしなければ[['''なりません''']]。 [SRC[>>5]] [FIG[ - [18] 実行中の [WEAK[([[スピン]]させた)]] [[タスク]]は実行を中断します。 [[イベント・ループ]]はそのまま [WEAK[(通常の終了と同じように)]] 次へと進めます。 - [19] 指定された条件が成立したら、 -- [20] 中断した[[タスク]]の続きを再開する[[タスクをキューに追加]]します。 [[タスク源]]は元の[[タスク]]と同じとします。 ]FIG] [25] [CODE(JS)@en[[[document.close]]]] は[[スピン]]するまで[[字句化]]を行います。 [51] [[媒体要素]]が[[文書から削除]]された後、次に[[イベント・ループ]]が[[スピン]]するより前に再度挿入されない場合、 [[ハードウェア資源]]に制約があればその機会にこれをすべて解放するのがよいとされています [SRC[]]。 *** スピンする状況 [21] [[スピン]]する[[算法]]には次のものがあります。 [FIG[ - [22] [[update the session history with the new page]] ([[素片識別子]]の示す場所まで[[スクロール]]するタイミング待ち) - [23] [CODE(DOMm)@en[[[showModalDialog]]]] ([[ダイアログ]]が閉じられるの待ち) - [24] [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[終了タグ]]の処理、 [[stop parsing]] (他の[[スクリプト]]の実行や[[スタイル・シート]]の準備完了や [[delay the loading]] 待ち) ]FIG] [59] [CODE(HTMLe)@en[[[script]]]] [[要素]]の処理で[[スピン]]する場合、その直前に [[HTML]] [[字句化器]]や[[XML構文解析器]]がブロックされ、直後にブロックが解除されます。 これにより、[[スピン]]中に当該[[字句化器]]・[[構文解析器]]を使うような[[タスク]]は実行されない、 とされています。 ;; [60] ブロックすると実行されない、という仕組みは十分に説明されていないように思えますが、 [[構文解析]]を行う[[タスク]]がキューに追加されなくなるので[[イベント・ループ]]が実行しなくなる、 ということでしょうか。既に[[タスク]]が[[タスク・キュー]]に追加されてしまっていれば、 それも実行してはいけないのですが、その場合同じ[[タスク・キュー]]を共有する他の[[タスク源]]の[[タスク]]は同様にブロックされてしまうのでしょうか。 ** 一時停止 [26] ある条件が満たされるまで[[利用者エージェント]]を[DFN[[RUBYB[一時停止]@en[pause]]]]する場合、 次のようにしなければ[['''なりません''']]。 [SRC[>>5]] [FIG[ = [27] [[非同期]]に実行されている[[算法]]があって[[安定状態を待つ]]状態なら、 [[同期区間]]を実行してから、 (適切であれば) [[非同期]]算法の実行を再開します。 = [28] 必要があれば、任意の [CODE(DOMi)@en[[[Document]]]] や[[閲覧文脈]]の[[レンダリング]]や[[利用者インターフェイス]]を更新して現在の状態を反映させます。 = [29] 条件が満たされるまで待ちます。 =- [30] [[イベント・ループ]]はこの間他の[[タスク]]を走らせては[['''なりません''']]し、 現在走っている[[タスク]]も[[ブロック]]しなければ[['''なりません''']]。 =- [31] [[利用者]]の入力に対しては反応し続ける[['''べき''']]ですが、 [[イベント・ループ]]が何も実行しないので、低能力で動作する[['''べき''']]です。 ]FIG] *** 一時停止する状況 [32] [[一時停止]]する[[算法]]には次のものがあります。 [FIG[ - [33] [[prompt to unload a document]] ([CODE(DOMe)@en[[[beforeunload]]]] の[[ダイアログ]]) - [34] [[obtain the storage mutex]] ([[storage mutex]] 待ち) - [35] [CODE(JS)@en[[[alert]]]] - [36] [CODE(JS)@en[[[confirm]]]] - [37] [CODE(JS)@en[[[prompt]]]] - [38] [[printing steps]] ([[印刷]]) ]FIG] * 利用者インターフェイスの無効化 [114] [[イベントループ]]とは直接関係ありませんが、[[利用者インターフェイス]]が[RUBYB[無効化]@en[disabled]]されることがあります。 [115] [CODE(DOMm)@en[[[showModalDialog]]]] による[[モーダルダイアログ]]の表示中は、その呼び出し元と同じ[[起源]]の[[閲覧文脈]] (正確には「[[背景閲覧文脈]]のリストに含まれる[[閲覧文脈]]」) の[[利用者インターフェイス]]を無効化しなければ[['''なりません''']] [SRC[]]。 [116] これはすなわち [SRC[]]、 - [117] [[利用者]]が [[navigate]] できなくする[['''べきです''']] - [118] [[利用者]]の操作によって[[イベント]]が送られないようにする[['''べきです''']] - [119] [[利用者]]が内容を編集できないようにする[['''べきです''']] - [120] [[利用者]]以外からの[[イベント]]の発生は止めません - [121] [[スクリプト]]の実行は中断しません - [122] [[アニメーション]]の実行は止めません [123] ということで、[[一時停止]]と似ていますが、[[同期区間]]などを実行しないこと、 [[利用者]]からの[[イベント]]を無視することが違っています。 * 非同期的に実行される算法 [43] [[Webブラウザー]]では次の算法がそれぞれ非同期的に実行されます。 [FIG[ - イベント・ループ -- メインの[[イベント・ループ]] (>>13) -- [[run a worker]] (ワーカーのイベント・ループ >>42) - 同期区間がある算法 -- 一覧は[[同期区間]]の項を参照 --- [CODE(HTMLe)@en[[[img]]]] や [CODE(HTMLe)@en[[[audio]]]] などにおける[[資源]]の扱いに関する算法 - その他の算法 (仕様上、「asynchronously」または「in the background」、「in parallel」と記されているもの) -- [[fetch]] (途中から) -- [CODE(JS)@en[[[document.load]]]] (途中から) -- [CODE(HTMLe)@en[[[canvas]]]] の [CODE(DOMm)@en[[[toBlob]]]] (途中から) -- [[downloading hyperlinks]] (途中から) -- [[navigate]] (途中から) -- [[application cache download process]] -- [CODE(DOMm)@en[[[setTimeout]]]]、[CODE(DOMm)@en[[[setInterval]]]] (途中から) -- [CODE(DOMi)@en[[[Worker]]]] [[構築子]] (途中から) -- [CODE(DOMi)@en[[[SharedWorker]]]] [[構築子]] (途中から) -- [CODE(DOMi)@en[[[EventSource]]]] の [[reestablish the connection]] -- [CODE(DOMm)@en[[[postMessage]]]] (途中から) -- [CODE(HTMLa)@en[[[ping]]]] の送信 -- [CODE(DOMi)@en[[[EventSource]]]] [[構築子]] (途中から) -- [CODE(DOMi)@en[[[WebSocket]]]] [[構築子]] (途中から) -- [[cache failure steps]] (一部) -- [[kill a worker]] -- [[terminate a worker]] -- [CODE(DOMm)@en[[[click]]]] 時のファイル選択ダイアログの表示 -- [[File API]] についての[[ファイル・システム]]からの読み込み -- [CODE(DOMm)@en[[[getRecordedData]]]] -- [CODE(DOMm)@en[[[createImageBitmap]]]] ]FIG] [47] 実際にはこの他に更に[[利用者インターフェイス]]など色々な要素が絡んできます。 [105] [CODE(DOMi)@en[[[ApplicationCache]]]] の [CODE(DOMm)@en[[[abort]]]] [[メソッド]]は[RUBYB[裏で動いている]@en[in the background]]処理に対して[DFN[[RUBYB[信号を送信]@en[send a signal]]]]します。 ** 停止 [72] ある[[算法]]が同時に実行中の他の[[算法]]を[RUBYB[停止]@en[abort]]させることがあります。 [FIG[ - [73] [[fetch]] はしばしば停止させられることがあります。 -- [74] [[update the image data]] -- [78] [[[CODE(HTMLe)@en[track]]処理モデルの開始]] -- [80] [CODE(DOMi)@en[[[EventSource]]]] の [CODE(DOMm)@en[[[close]]]] -- [81] [CODE(DOMi)@en[[[EventSource]]]] の [[forcibly close]] -- [82] [CODE(DOMi)@en[[[EventSource]]]] が[[ごみ収集]]された場合 - [75] [[媒体要素読込算法]]が[[資源選択算法]]を停止させることがあります。 - [76] [[seek]] が同時に実行中の [[seek]] を停止させることがあります。 - [79] [[ワーカーを殺す]][[算法]]、[[ワーカーを終端させる]][[算法]]は実行中の[[スクリプト]]を停止させます。 - [77] [[[CODE(HTMLe)@en[track]]処理モデルの開始]]は他の[[算法]]は停止させませんが、 その代わりに動作中の同じ[[算法]]に処理を委ねて自身が停止します。 ]FIG] * 待ち [70] 仕様上、特定の条件が満たされるまで[RUBY[待つ]@en[wait]]ことが求められている場合があります。 条件は[[イベント・ループ]]の状態であったり、[[利用者]]の操作であったり、 [[OS]] の状態であったり色々ですが、いずれにせよ単純な[[イベント・ループ]]の逐次実行とは異なる動作が起こります。 @@ 完全なリストがあると良いが多い [FIG[ - [101] [[encoding sniffing algorithm]] -- [[利用者エージェント]]依存ながらも 500ms または 1024 バイトの早い方まで待つのがよいとされています - [102] [CODE(DOMm)@en[[[setTimeout]]]], [CODE(DOMm)@en[[[setInterval]]]] -- [103] [[著者]]が指定した時間 + [[利用者エージェント]]定義の時間、待つこととなっています ]FIG] ;; >>97 も参照してください。 ** 他のタスクを待つ [94] 次の[[算法]]では、途中の[[段階]]で別の[[タスク]]の完了を待ちます。 [FIG[ - [92] [[resource fetch algorithm]] - [93] [[resource selection algorithm]] ]FIG] * 実行タイミング [97] いくつかの処理は、指定された時間が経過するのを待って実行されます。待ち (>>70) も参照してください。 [FIG[ - [98] [[resource fetch algorithm]] [SRC[HTML]] -- [CODE(DOMe)@en[[[progress]]]] [[イベント]]の[[発火]]は 350ms (±200ms) ごと、または1[[バイト]]受信のいずれか遅い方で行わなければ[['''なりません''']] - [99] [[stall timeout]] [SRC[HTML]] -- [RUBYB[利用者エージェント定義の時間]@en[user-agent defined length of time]] (3秒くらいとする[['''べき''']]) で発生 - [100] [[DnD]] 処理 [SRC[HTML]] -- 350ms (±200ms) ごとに行わなければ[['''なりません''']] - [104] [[make progress notifications]], [[make upload progress notifications]] [SRC[[[XHR]]]] -- [CODE(DOMe)@en[[[progress]]]] [[イベント]]の[[発火]]は 50ms ごと、または1[[バイト]]受信のいずれか遅い方で行わなければ[['''なりません''']] - [107] [CODE(HTML)@en[<[[meta]] [[http-equiv]]=[[Refresh]]>]] [SRC[HTML]] - [108] [CODE(HTTP)@en[[[Refresh:]]]] [[ヘッダー]] [SRC[仕様なし]] ]FIG] * レンダリングの更新 [52] [[ワーカー]]でないメインの[[イベントループ]]では、レンダリングの更新は1回の繰り返しの最後のステップです。 このタイミングで具体的に何を行うかは明確に定義されているわけではありませんが、次のものが含まれています。 [FIG[ - [53] [[canvas]] における[[利用者へ通知]] ([[タスク]]内で同期的に行なって良いしこのタイミングで行なっても良いし、行わなくても良い) - [113] 外部参照を含む[[スタイルシート]]に[[スクリプト]]がアクセスできるようになるのは、 最初のレンダリング更新のタイミング以降です。 -- ]FIG] ;; [124] 仕様上は[[イベントループ]]で毎回[[レンダリング]]の更新を行うことになっていますが、 実際の[[Webブラウザー]]は必ずしもそう実装されているわけではないようです。 * 構文解析器との関係 [61] [[HTML]] の[[構文解析器]] [WEAK[(や、ちゃんと規定した仕様書が存在していませんが、 [[XML]] の[[構文解析器]])]] は、それ自体は[[タスク]]の一部や全部ではなく、[[イベント・ループ]]とは概念として独立しています。 [62] [CODE(HTMLa)@en[[[innerHTML]]]] のように完全に[[タスク]]に含まれる処理の一部分として構文解析が実行されることもあれば、 [[fetch]] によって[[ネットワーク]]からデータを取得する度に順次生成されていく一連の[[タスク]]によって断続的に構文解析が進められることもあります。 * イベント・ループとの相互作用が不明なもの [46] [[HTML]] 以前に規定されたものや、 [[HTML]] 以後であっても明確な仕様が存在しないものは、 [[イベント・ループ]]とどう相互作用するのか文書化されていません。 [63] [[fetch]] が[[画像]]や [[XML]] の[[タスク]]を複数生成する時に、 それを[[インクリメンタル・レンダリング]]する処理モデルは定義されていません。 [45] [[XSLT]] の処理と[[イベント・ループ]]の関係は定義されていません。 [SRC[>>44]] [64] [[アニメーションGIF]]の[[レンダリング]]との関係は定義されていません。 ただし同じ[[URL]]の[[アニメーションGIF]]は、最後に読み込まれたものの再生と同期する、 と [[HTML]] により規定されています。 [67] [CODE(HTMLe)@en[[[video]]]] や [CODE(HTMLe)@en[[[audio]]]] の再生の具体的なタイミングは規定されていません。 ([[イベント・ループ]]とは独立に、それぞれのタイミングに合わせて再生されるべきなのでしょう。) なお [CODE(HTMLe)@en[[[track]]]] の[[レンダリング]]は[[媒体要素]]の[[レンダリング]]に合わせて更新しなければならないと規定されています。 * 原子的に実行されるべきもの [95] いくつかの[[算法]]の一部分は[RUBYB[原子的]@en[atomic]]に実行するよう規定されています。 @@ XXX 一覧 * 歴史 [4] [[イベント・ループ]]の概念は [[Web Applications 1.0]] ([[HTML Living Standard]]) によってはじめて体系的に説明、仕様化されました。 [87] [[イベント・ループ]]は最初に [[Web Workers]] において[[ワーカー]]の挙動を説明するために導入されました。 [REFS[ - [88] [CITE@en-US-x-hixie[Web Workers]] ([TIME[2013-02-09 03:43:01 +09:00]] 版) ]REFS] [89] 更にその後、[[メイン・スレッド]]についても[[イベント・ループ]]が定義されるようになりました。 [[タスク]]の概念もこの時導入されました。 @@ ... [REFS[ - [2] [CITE@en[Web Applications 1.0 r6966 Allow browsers to bail early for showModalDialog, alert, confirm, and prompt during pagehide, beforeunload, and unload events.]] ( ([TIME[2012-02-07 07:54:00 +09:00]] 版)) ]REFS] [86] [[ワーカー]]の[[イベント・ループ]]はメインの[[イベント・ループ]]と同じように処理されますが、 >>87、>>89 という経緯からか当初は [[run a worker]] [[算法]]に組み込まれており、 [RUBYB[[[閉じ中]]]@en[closing]][[フラグ]]の存在など微妙に定義が違っていました。 しかし >>85 によって両者の定義が統合されました。 [REFS[ - [85] [CITE@en[Web Applications 1.0 r7696 Integrate the 'event loop' mechanism of workers and windows together, and try to specify which is meant when it might be ambiguous.]] ([TIME[2013-02-06 09:24:00 +09:00]] 版) ]REFS] * 関連 [12] [[イベント・ループ]]は、[[ストレージ・ミューテックス]]を所有することができます。 ;; [39] [[ストレージ・ミューテックス]]は[[利用者エージェント]]全体で1つなので、 [[ストレージ・ミューテックス]]の解放待ちのために[[イベント・ループ]]全体がブロックされることがあります。 [55] [[イベント・ループ]]は [[termination nesting level]] を持ちます。 [54] [CODE(JS)@en[[[window.length]]]] は同じ[[イベント・ループ]]で動作しているかどうかによって挙動が変わり得ます。 * メモ [1] [CITE@en[Timing and Synchronization in JavaScript - Opera Developer Community]] ([TIME[2009-06-07 11:12:38 +09:00]] 版) @@ [83] [[IndexedDB]] [106] [CITE@en[Web Applications 1.0 r7980 Lay the groundwork for DOM Core to handle reentrant mutation observers.]] ( ([TIME[2013-06-15 07:32:00 +09:00]] 版)) [109] [CITE[IRC logs: freenode / #whatwg / 20130701]] ( ([TIME[2013-07-02 23:22:48 +09:00]] 版)) [110] [CITE@en[Bug 22522 – WebIDL, error handling, and promises]] ( ([TIME[2013-07-02 23:40:42 +09:00]] 版)) [111] [CITE[IRC logs: freenode / #whatwg / 20130701]] ( ([TIME[2013-07-02 23:22:48 +09:00]] 版))