/
612.txt
716 lines (538 loc) · 47.7 KB
/
612.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
[3] [[Webブラウザー]]における[[イベント]]、[[fetch]]、[[構文解析]]、[[スクリプト]]実行、
[[レンダリング]]その他の動作の相互作用は、
[DFN[[RUBYB[[[イベントループ]]]@en[event loop]]]]によって説明されています。
[15] 非同期システム、 [[GUI]] システムの同様の概念に倣って[[イベントループ]]と呼ばれていますが、
実際に [[Webブラウザー]]で実行される処理の単位は[[イベント]]ではなく、[[タスク]]と呼ばれています。
[[JavaScript]] で利用される [[DOM]] の[[イベント]]は[[タスク]]であることもあれば、[[タスク]]の処理の一部分であることもあります。
;; [81] 入出力装置やネットワークの入出力のような [[Webブラウザー]]外の“イベント”
は、それを処理する[[タスク]]として [[Webブラウザー]]の[[イベントループ]]における[[タスクキュー]]に追加されることになります。
[207] 1つの[[Webブラウザー]]上では、複数の [[Webサイト]]などが同時に[[レンダリング]]・動作しています。単一の[[Webページ]]も、[[閲覧文脈]]本体の他、複数の[[ワーカー]]が[[並行]]して動作することがあります。そのため[[イベントループ]]も同時に複数存在することがあります。
[96] 本項では[[イベントループ]]の他、非同期的な処理の実行や並行的な処理の実行など、
[[Webブラウザー]]における処理のタイミングと関係にまつわる事項全般を扱います。
;; [82] その他にも[[Webブラウザー]]は[[利用者インターフェイス]]の処理や [[OS]]
とのやり取りなど、[[Webページ]]の[[相互運用性]]には関わらない様々な処理が必要になります。[[Webブラウザー]]の実装手法としての“[[イベントループ]]”と、
仕様上の (= [[著者]]の[[スクリプト]]から見た) [[イベントループ]]は必ずしも一致しません。
* 仕様書
[REFS[
- [5] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#event-loops>'''
- [40] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#the-event-loop>'''
- [204] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#worker-event-loop>
- [41] '''[CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#run-a-worker>'''
- [44] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-03-28 21:58:58 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#scriptTagXSLT>
- [200] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2014-05-08 22:12:35 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#serializability-of-script-execution>
- [90] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#termination-nesting-level>
]REFS]
* イベントループ
[6] [[利用者エージェント]]は、[[イベント]]、[[利用者]]との対話、[[スクリプト]]、
[[レンダリング]]、[[ネットワーク]]処理、その他の協調のために[[イベントループ]]を使わ[['''なければなりません''']]。
[[イベントループ]]は[[利用者エージェント]]毎に少なくても1つ[['''なければなりません''']]。
[[関係する類似起源閲覧文脈の単位]]毎に高々1つの[[イベントループ]]を有することができます。
[SRC[>>5]]
;; [8] つまり、[[利用者エージェント]]全体で1つの[[イベントループ]]を共有することもできますし、
[[タブ]]毎などの単位で複数の[[イベントループ]]に分けることもできるのですが、
その分け方として、 ([CODE(JS)@en[[[document.domain]]]] を考慮した)
[[起源]]ごとのグループを分離してはいけない、ということです。
;; [9] 仕様上明記されていませんが、おそらくここでいう「[[利用者エージェント]]」
の単位は恣意的に決めることができ、
例えば通常モードと秘密モードがあり、両者で開いている [[Web頁]]同士が同じ[[起源]]であっても [[JavaScript]]
でアクセスできないなら、これは2つの[[利用者エージェント]]であり、
この規定に違反せずに別々の[[イベントループ]]を有することができるはずです。
;; [7] 1つの[[関連する類似起源閲覧文脈の単位]]に対して複数の[[イベントループ]]があると、
そこに属するいずれかの[[閲覧文脈]]が他の[[関連する類似起源閲覧文脈の単位]]に属するような
[[navigate]] が発生した時に複雑なことになります。 HTML 仕様はそれをどう処理するか現在定義していません。
[SRC[>>5]] (複雑なこと、というのは具体的には示されていません。)
[55] [[イベントループ]]は次の状態を持ちます。
[FIG(list members)[
:[[タスクキュー]]:1つ以上の[[タスクキュー]]を持ちます [SRC[>>5]]。個数は実装に依存します。
:[[マイクロタスクキュー]]:1つの[[マイクロタスクキュー]]を持ちます [SRC[>>5]]。
:[[閲覧文脈]]群または[[ワーカー]]:
[10] [[ワーカー]]以外の[[イベントループ]]は、最低1つ[[閲覧文脈]]を持ちます [SRC[>>5]]。
[42] [[ワーカー]] ([CODE(DOMi)@en[[[WorkerGlobalScope]]]]) は、
それぞれ別個の[[イベントループ]]を有します [SRC[>>40, >>204]]。
:[[現在走っているタスク]]:動作中の[[タスク]]または[[マイクロタスク]]が高々1つ存在します。
:[[termination nesting level]] [SRC[>>90]]:[[モーダルダイアログ]]の表示を制御するものです。
:[[マイクロタスクチェックポイントを行っている]]フラグ:[[マイクロタスク]]参照。
:[[ストレージミューテックス]]:[[ストレージ]]へのアクセスを制御するための[[ミューテックス]]を保持した状態になることがあります。
]FIG]
[11] [[イベントループ]]のすべての[[閲覧文脈]]が捨てられる時、[[イベントループ]]自体も捨てられます。
逆に[[閲覧文脈]]は1つ[[イベントループ]]を持ちます。
[91] [[ワーカー]]の[[イベントループ]]は[[閲覧文脈]]ではなく、[[ワーカー]]に関連付けられています。
[[ワーカー]]が閉じられた時に[[イベントループ]]も捨てられます。
[161] [[イベントループ]]が実行する処理の単位は[[タスク]]と呼ばれます。
特定の[[イベントループ]]が同時に実行する[[タスク]]は高々1つであり、
[DFN[[RUBYB[[[現在走っているタスク]]]@en[currently running task]]]]と呼ばれます。
[[現在走っているタスク]]の初期値は [[null]] です。 [SRC[>>5]]
;; [163] [[現在走っているタスク]]は[[イベントループ]]全体によって[[タスク]]に設定される場合 (>>13)
の他、[[マイクロタスクチェックポイント]]によって[[マイクロタスク]]に設定される場合もあります。
;; [63] [[レンダリングの更新]]からは[[現在走っているタスク]]は設定されないので、
[[アニメーションフレームコールバック]]の実行中は [[null]] のままです。
;; [195] [[現在走っているタスク]]は、 (仕様書上必ずしも明示はされていませんが)
[[タスク]]内の各[[アルゴリズム]]から、その[[タスク]]の種類を調べるため参照されます。
例えば [[allowed to show a popup]] は、[[クリック]]系の[[イベント]]に由来する[[タスク]]の処理中かどうかで分岐します。
[128] 更に、[[最上位閲覧文脈]]はそれぞれ[RUBYB[[[セッション履歴イベントループ]]]@en[session history event loop]]を持ちます。
セッション履歴イベントループはメインやワーカーの[[イベントループ]]とは異なり履歴管理専用で、とても単純になっています。
(用語定義上は[[セッション履歴イベントループ]]は[[イベントループ]]ではありません。)
[71] 「[[要素]]の[[イベントループ]]」は明確に定義されていませんが[[要素]]の[[文書]]が属する[[閲覧文脈]]が属する[[イベントループ]]を指すようです。
;; 用例:
[REFS[
- [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2012-11-16 20:26:18 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#commit-the-scratch-bitmap>
]REFS]
** 実行
[13] メインやワーカーの[[イベントループ]]は、それが存在し続ける限り、次の手順を連続的に走らせなければ[['''なりません''']] [SRC[>>5]]。
[FIG(steps)[
= [74] [[タスク]]があれば実行します (>>75)。
= [184] [[マイクロタスクチェックポイントを行います]]。
= [186] [[レンダリングの更新]]を実行します。
= [187] [[ワーカー]]で、[CODE(DOMi)@en[[[WorkerGlobalScope]]]] の[RUBYB[[[閉じ中]]]@en[closing]][[フラグ]]が[[真]]なら、
[[イベントループ]]を[RUBYB[破棄]@en[destroy]]して本手順群を停止します。
= [188] 最初に戻ります。
]FIG]
;; [16] [[イベントループ]]とは別に、[[算法]]の一部分が[[非同期]]的に実行されると規定されているものがあります。
そのような[[算法]]についても、結果を何らかの形で [[DOM]] に反映させる必要があり、
[[イベントループ]]が[[安定状態を提供]]することによってそのような[[算法]]の[[同期区間]]が実行される、
あるいは[[タスクキュー]]に[[タスク]]を追加する、といった形で[[イベントループ]]と統合されています。
[[マルチスレッド]]な実装なら[[同期区間]]の前後の[[非同期]]な部分は[[イベントループ]]とは別の[[スレッド]]で実装してもよいでしょうし、単一[[スレッド]]なら仕様上の[[イベントループ]]を含むより大きな[[イベントループ]]の中で交互に処理を行うことになるのでしょう。
[WEAK[(単一[[スレッド]]の [[Webブラウザー]]があるのか知りませんが...)]]
[53] [[イベントループ]]の手順中で[[タスク]]と[[マイクロタスク]]の実行では[[著者]]による[[スクリプト]]が実行される可能性があります。
また[[レンダリングの更新]]でも[[アニメーションフレームコールバック]]などとして[[著者]]による[[スクリプト]]が実行されることがあります。
** タスクの実行
[75] [[イベントループ]]における[[タスク]]の処理は、次のように行います。
[FIG(steps)[
= [178] いずれかの[[タスクキュー]]を選んで、そこに[[タスク]]があれば、最古のものを選びます。なければここで終わります。
-- ただし、[[タスク]]に関連付けられた [CODE(DOMi)@en[[[Document]]]] が[[完全に活性]]でないものは無視します。
-- ここで[[利用者エージェント]]は任意の[[タスクキュー]]を選んで構いません。
= [179] 選んだ[[タスク]]を[[現在走っているタスク]]とします。
= [180] '''選んだ[[タスク]]を実行します。'''
= [181] [[現在走っているタスク]]を [[null]] とします。
= [182] [[イベントループ]]が [[storage mutex]] を所有していれば、これを[[解放]]します。
= [183] 実行した[[タスク]]を[[タスクキュー]]から削除します。
]FIG]
;; [162] 最初の[[タスク]]の選択のタイミングのことを、仕様書では >>48 の通りしばしば「手順1」
と呼んで参照しています。
;; [76] [[イベントループ]]の一巡の間に[[タスク]]は高々1つだけ実行されます。
それに対して[[マイクロタスク]]や[[アニメーションフレームコールバック]]は、
実行できる状態のものがすべて実行されます。これが[[タスク]]に対して[[マイクロタスク]]が
「マイクロ」である所以です。
[84] [[タスクキュー]]は[[タスク源]]単位で存在していますから、
同じ[[タスク源]]の[[タスク]]についてはキューに入っている順序で実行されることが保証されますが、
異なる[[タスク源]]の[[タスク]]同士は[[利用者エージェント]]の裁量でどちらを先に実行しても良いことになります。
[14] この辺の処理は、[[利用者エージェント]]が実行される [[OS]]
や実装に使っている[[ライブラリー]]等の影響を受けることもあるでしょうし、
あるいは何を優先的に実行するかは[[実装の品質]]の問題であって
[[Webブラウザー]]実装者が工夫して競合するべき点でもあるでしょうから、
仕様としてはあまり具体的に規定せず、かなり自由度を持たせているようです。
何をどのような順序で処理するかが[[相互運用性]]にあまり影響しないということもあります。
[105] [[WebSocketメッセージ受信]]における[[タスク]]の実行では、
[[タスク]]の実行に必要な [[I/O]] 処理を待つ間他の[[タスクキュー]]を実行するような効率化が推奨されています。
[129] [[完全に活性]]でない[[文書]]に関する[[タスク]]は、選択時に無視されます。
[[タスク]]が無視されるわけではありませんから、再び[[完全に活性]]に戻ったら実行される可能性はあります。
** 手順1到達時点の状態
[48] 次に示すものは、「[RUBYB[最後に[[イベントループ]]の手順1に到達した時]@en[last time the event loop reached step 1]]」
の状態を定義に含めています。
[FIG(list)[
- [49] [[スクリプトをブロックしているスタイルシート]]
- [50] [CODE(DOMa)@en[[[ended]]]] [[属性]] ([[媒体要素]])
- [57] [CODE(DOMi)@en[[[WebSocket]]]] の [CODE(DOMa)@en[[[bufferedAmount]]]]
- [58] [CODE(DOMi)@en[[[WebSocket]]]] の[[ごみ収集]]
- [65] [CODE(HTMLe)@en[[[embed]]]] [[要素]]の [[potentially active]]
-- [[文書中]]にあるか否か
-- [[レンダリング中]]であるか否か
- [208] 選択状態にある [[video track]] や [[audio track]] の決定
-- [209] [CITE@en[Web Applications 1.0 r8673 Make sure that we say that enabling audio tracks and selecting video tracks is all synchronised with the event loop]] ([TIME[2014-06-12 07:25:00 +09:00]] 版) <http://html5.org/r/8673>
]FIG]
;; [56] かつては
「[RUBYB[最後に[[イベントループ]]が[[タスク]]を実行しはじめた時]@en[last time the event loop started executing a task]]」
とも呼ばれていましたが、 >>48 の表現に統一されました。
[158] 次に示すものは、「[RUBYB[次に[[イベントループ]]の手順1に到達する前]@en[before the next time the event loop reaches step 1]]」を定義に含めています。
[FIG(list)[
- [51] [[媒体要素]]が[[文書から削除]]された後、この時点までに再度挿入されない場合、
[[ハードウェア資源]]に制約があればその機会にこれをすべて解放するのがよいとされています
[SRC[<http://www.whatwg.org/specs/web-apps/current-work/#best-practices-for-implementors-of-media-elements>]]。
]FIG]
[68] また、次に示すものは、同じ[[タスク]]内であれば同じ結果になることが求められています。
[FIG(list)[
- [69] [CODE(DOMa)@en[[[canvasResolution]]]] の値や、[[ビットマップ]]作成時に使う[[解像度]]
]FIG]
;; [211] 同じ「[[タスク]]」ということは、[[スピン]]によって[[タスク]]が中断された場合、
再開後に同じ値であるとは限りません。
[66] これらは、次の [[event loop level 1]] に到達する前に実装が保持する値を更新したり、
新たな状態を反映させるための処理を行ったりする必要があります。
[EG[
[124] [CODE(HTMLe)@en[[[embed]]]] [[要素]]では、状態を更新するための[[タスク]]を[[タスクキューに追加]]する必要があるかもしれません。
]EG]
** スピン
[212] [DFN[[RUBYB[[[イベントループをスピン]]]@en[spin the event loop]]]]は、
一種の[[継続]]で、一旦現在の処理を中断して[[イベントループ]]に制御を戻し、
指定した条件が達成された後に再開するものです。
[17] [[イベントループ]]を[[スピン]]する場合、次のように処理します [SRC[>>5]]。
[FIG(steps)[
= [164] [VAR@en[task]] を[[現在走っているタスク]]とします。
= [165] [VAR@en[task source]] を [VAR@en[task]] の[[タスク源]]とします。
= [166] [VAR@en[old stack]] を[[スクリプト設定群オブジェクトのスタック]]の複製とします。
= [168] [[global script clean-up jobs]] を実行します。
= [169] [[マイクロタスクチェックポイント]]を実行します。
= [167] [[スクリプト設定群オブジェクトのスタック]]を空にします。
= [18] [VAR@en[task]] を停止させ、 [VAR@en[task]] を呼び出したアルゴリズムの続きへと進ませます。
]FIG]
;; [173] [[スピン]]は[[イベントループ]]から直接呼び出された[[タスク]]から呼び出されることもあれば、
[[マイクロタスク]]や[[複合マイクロタスク部分タスク]]から呼ばれることもあります。
;; [213] [[スクリプト設定群オブジェクト]]には[[スクリプト]]の実行環境その他が含まれていますので、
それら処理に必要な状態すべてが保存された状態で、実行が中断され、
[[イベントループ]]や[[マイクロタスクチェックポイント]]などの次のステップへと進むことになります。
[19] その後指定された条件が成立したら、[[タスク源]] [VAR@en[task source]]
において次のような[[タスクをキューに追加]]します [SRC[>>5]]。
[FIG(steps)[
= [170] [[スクリプト設定群オブジェクトのスタック]]を [VAR@en[old stack]] とします。
= [171] [[スピン]]元に戻ります。
]FIG]
[25] [CODE(JS)@en[[[document.close]]]] は[[スピン]]するまで[[字句化]]を行います。
[DEL[
[51] [[媒体要素]]が[[文書から削除]]された後、次に[[イベントループ]]が[[スピン]]するより前に再度挿入されない場合、
[[ハードウェア資源]]に制約があればその機会にこれをすべて解放するのがよいとされています
[SRC[<http://www.whatwg.org/specs/web-apps/current-work/#best-practices-for-implementors-of-media-elements>]]。
]DEL]
;; [159] 本規定は >>51 に変更されました [SRC[>>160]]。
;; [140] [[スピン]]によって実行中の[[タスク]]は中断されますが、[[イベントループ]]が中断しているわけではないので、
[[スピン]]後に新たに追加された[[タスク]]はそのまま実行されます。
[172] [[HTML Standard]] では >>17 の通り[[タスク]]の実行を中断して条件が成立してから再開する形を採っていますが、
実際の [[Webブラウザー]]では [[JavaScriptエンジン]]の仕様上そのように中断させることは難しく、
[[イベントループ]]自体を再帰的に実行しているようです。
*** スピンする状況
[21] [[スピン]]する[[算法]]には次のものがあります。
[FIG(list)[
- [22] [[update the session history with the new page]] ([[素片識別子]]の示す場所まで[[スクロール]]するタイミング待ち)
- [23] [CODE(DOMm)@en[[[showModalDialog]]]] ([[ダイアログ]]が閉じられるの待ち)
- [24] [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[終了タグ]]の処理
- [210] [[stop parsing]] (他の[[スクリプト]]の実行や[[スタイル・シート]]の準備完了や
[[delay the loading]] 待ち)
]FIG]
[80] このうち [[update the session history with the new page]] は[[利用者エージェント]]が[[イベントループ]]上の任意のタイミングで実行できますし、
[[スピン]]前の処理が後の処理に直接的に影響を及ぼしてもいないため、
実質的に次の処理のための[[タスク]]をキューに入れるのと変わらないと思われます。
[125] [[stops parsing]] における[[スピン]]は、[[スピン]]を使わない形に読み替えられます。
([[stops parsing]] 参照。)
*** 歴史
[REFS[
- [139] [CITE['''['''whatwg''']''' Bug in 12.2.5.4.8 (The "text" insertion mode) when invoking the "spin the event loop" algorithm]] ([TIME[2013-10-01 22:14:47 +09:00]] 版) <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-October/040949.html>
]REFS]
** 字句化器のブロック
[59] [CODE(HTMLe)@en[[[script]]]] [[要素]]の処理で[[スピン]]する場合、その直前に [[HTML]]
[[字句化器]]や[[XML構文解析器]]がブロックされ、直後にブロックが解除されます。
これにより、[[スピン]]中に当該[[字句化器]]・[[構文解析器]]を使うような[[タスク]]は実行されない、
とされています。
;; [60] ブロックすると実行されない、という仕組みは十分に説明されていないように思えますが、
[[構文解析]]を行う[[タスク]]がキューに追加されなくなるので[[イベント・ループ]]が実行しなくなる、
ということでしょうか。既に[[タスク]]が[[タスク・キュー]]に追加されてしまっていれば、
それも実行してはいけないのですが、その場合同じ[[タスク・キュー]]を共有する他の[[タスク源]]の[[タスク]]は同様にブロックされてしまうのでしょうか。
[152] [[HTML字句化器]]や [[XML構文解析器]]を使う[[タスク]]というのは、どうやら実際には、
[[HTML]] や [[XML]] の[[ファイル]]を [[fetch]] した結果としてバイト列を受信する度に追加される[[タスク]]のことを指しているようです。
つまりブロックされている間はそれ以上先に[[字句化]]が進まないという規定であるわけです。
[[文書]]に関連付けられた[[HTML構文解析器]]や[[XML構文解析器]]が利用されるのは、[[文書]]自体の[[構文解析]]を除けば、
[[HTML文書]]における [CODE(JS)@en[[[document.write]]]]/[CODE(JS)@en[[[document.writeln]]]] の呼び出しだけのようです。
そちらは定義上、[[字句化器]]がブロックされるのと同じ条件下で [[HTML構文解析器]]を呼び出さないことになっています。
(なのでいずれにせよ[[字句化器]]は止まって先に進みません。)
[REFS[
- [150] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2014-01-31 21:26:12 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-incdata>
- [151] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2014-01-31 21:26:12 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#parsing-xhtml-documents>
]REFS]
** 一時停止
[26] ある条件が満たされるまで[[利用者エージェント]]を[DFN[[RUBYB[一時停止]@en[pause]]]]する場合、
次のようにしなければ[['''なりません''']]。 [SRC[>>5]]
[FIG(steps)[
= [27] [DEL[[[非同期]]に実行されている[[算法]]があって[[安定状態を待つ]]状態なら、[[同期区間]]を実行してから、 (適切であれば) [[非同期]]算法の実行を再開します。]]
=- [199] >>198 により削除されました。
= [28] 必要があれば、 [CODE(DOMi)@en[[[Document]]]] や[[閲覧文脈]]の[[レンダリング]]や[[利用者インターフェイス]]を更新して現在の状態を反映させます ([[レンダリングの更新]])。
= [29] 条件が満たされるまで待ちます。
=- [30] [[イベントループ]]はこの間他の[[タスク]]を走らせては[['''なりません''']]し、
現在走っている[[タスク]]も[[ブロック]]しなければ[['''なりません''']]。
=- [31] [[利用者]]の入力に対しては反応し続ける[['''べき''']]ですが、
[[イベントループ]]が何も実行しないので、低能力で動作する[['''べき''']]です。
]FIG]
[127] [[一時停止]]中の[[レンダリング]]については、[[モーダルダイアログ]]も参照。
[223] [[一時停止]]中でも[[動画]]の[[再生]]や[[アニメーション]]は続行するべきかもしれません。
[32] [[一時停止]]する[[算法]]には次のものがあります。
[FIG(list)[
- [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]
[220] [[pause]] 中は他の[[タスク]]を実行できないというのが仕様上の規定ですが、
[[Firefox]] では[[モーダルダイアログ]]の表示中に [[Bookmarklet]]
を実行できる (つまり [[navigate]] から[[スクリプト]]実行の[[タスク]]が実行される)
ようです。 [TIME[2015-09-11T11:19:54.000Z]]
[221] 1つの[[利用者エージェント]]が複数の[[イベントループ]]を使う場合、
ある[[イベントループ]]が[[一時停止]]中でも、他の[[イベントループ]]は動作するかもしれません。
[EG[
[222] ある[[起源]]の[[スクリプト]]が[[モーダルダイアログ]]を表示していても、
他の[[起源]]の [[Webページ]]は通常通り表示・操作できるのが好ましいと考えられます。
]EG]
** 一時中断
[218] [[ワーカー]]は、[RUBYB[[[一時中断]]]@en[suspend]]されることがあります。
[[イベントループ]]の実行も中断されるようです。
;; [[ワーカー]]参照。
* 利用者インターフェイスの無効化
[114] [[イベントループ]]とは直接関係ありませんが、[[利用者インターフェイス]]が[RUBYB[無効化]@en[disabled]]されることがあります。
[115] [CODE(DOMm)@en[[[showModalDialog]]]] による[[モーダルダイアログ]]の表示中は、その呼び出し元と同じ[[起源]]の[[閲覧文脈]]
(正確には「[[背景閲覧文脈]]のリストに含まれる[[閲覧文脈]]」) の[[利用者インターフェイス]]を無効化しなければ[['''なりません''']]
[SRC[<http://www.whatwg.org/specs/web-apps/current-work/#dom-showmodaldialog>]]。
[116] これはすなわち [SRC[<http://www.whatwg.org/specs/web-apps/current-work/#dom-showmodaldialog>]]、
[FIG(list)[
- [117] [[利用者]]が [[navigate]] できなくする[['''べきです''']]
- [118] [[利用者]]の操作によって[[イベント]]が送られないようにする[['''べきです''']]
- [119] [[利用者]]が内容を編集できないようにする[['''べきです''']]
- [120] [[利用者]]以外からの[[イベント]]の発生は止めません
- [121] [[スクリプト]]の実行は中断しません
- [122] [[アニメーション]]の実行は止めません
]FIG]
[123] ということで、[[一時停止]]と似ていますが、[[同期区間]]などを実行しないこと、
[[利用者]]からの[[イベント]]を無視することが違っています。
[146] [[inert]] も類似した状況を作り出します。 [[inert]] は [DEL[[CODE(HTMLa)@en[[[inert]]]] [[属性]]や]]
[CODE(HTMLe)@en[[[dialog]]]] [[要素]]によって発生します。
* 待ち
[70] 仕様上、特定の条件が満たされるまで[RUBY[待つ]@en[wait]]ことが求められている場合があります。
条件は[[イベント・ループ]]の状態であったり、[[利用者]]の操作であったり、
[[OS]] の状態であったり色々ですが、いずれにせよ単純な[[イベント・ループ]]の逐次実行とは異なる動作が起こります。
@@ 完全なリストがあると良いが多い
[FIG(list)[
- [101] [[encoding sniffing algorithm]]
-- [[利用者エージェント]]依存ながらも 500ms または 1024 バイトの早い方まで待つのがよいとされています
- [147] [CODE(HTML)@en[[[<input type=file>]]]] の[[活性化動作]]は、前回の実行が完了するまで待ったり、
[[利用者]]による[[ファイル]]の選択が終わるまで待ったりします。
- [148] [CODE(DOMe)@en[[[input]]]] [[イベント]]を [CODE(HTMLe)@en[[[input]]]] [[要素]]や [CODE(HTMLe)@en[[[textarea]]]]
[[要素]]で[[発火]]する[[タスク]]を[[キュー]]に入れる前に[[利用者]]の動作を適当に (例えば 100ms くらい) 待っても構いません。
- [153] [[start the [CODE(HTMLe)@en[track]] processing model]] の途中で待つことがあります。
- [174] [[スピン]] (>>17)
- [190] [[display steps]] 実行前に[[通知]]できるようになるまで待つ
-- [CITE@en-US[Notifications API Standard]] ([TIME[2014-02-11 16:20:34 +09:00]] 版) <http://notifications.spec.whatwg.org/#pending-notifications>
- [[update the image data]]
-- [[マイクロタスク]]をキューに入れる条件が達成されるまで待ちます
- [[セッション履歴イベントループ]]は、[[タスク]]がキューに入れられるまで待ちます。
- [[WebSocket接続の確立]]
- [[ワーカーを殺す]]際、[[利用者エージェント]]依存の時間待ちます。
]FIG]
[154] 「待つ」という語を使って定義されているものの、「待つ」を使わない単純な形に容易に読み替えられるもの:
[FIG(list)[
- [155] [CODE(JS)@en[[[navigator.languages]]]] の値が変化する場合の処理
]FIG]
;; タイマー (>>97) も参照してください。
** 他のタスクを待つ
[94] 次の[[算法]]では、途中の[[ステップ]]で別の[[タスク]]の完了を待ちます。
[FIG(list)[
- [92] [[resource fetch algorithm]]
- [93] [[resource selection algorithm]]
]FIG]
** Fetch を待つ
[141] 次の[[算法]]では、途中の[[ステップ]]で [[fetch]] の完了を待ちます。
[FIG(list)[
- [[navigate]]
- [142] [CODE(DOMm)@en[[[importScripts]]]]
- [191] [[display steps]]
-- [CITE@en-US[Notifications API Standard]] ([TIME[2014-02-11 16:20:34 +09:00]] 版) <http://notifications.spec.whatwg.org/#display-steps>
- [192] [[replace steps]]
-- [CITE@en-US[Notifications API Standard]] ([TIME[2014-02-11 16:20:34 +09:00]] 版) <http://notifications.spec.whatwg.org/#replace-steps>
@@
- [[XHR]] ([[async]] = false)
- [[document.load]] ([[async]] = false)
]FIG]
* タイマー
[97] いくつかの処理は、指定された時間が経過するのを待って実行されます。待ち (>>70) も参照してください。
[FIG(list)[
- [102] [CODE(DOMm)@en[[[setTimeout]]]], [CODE(DOMm)@en[[[setInterval]]]]
-- [103] [[著者]]が指定した時間 + [[利用者エージェント]]定義の時間、待つこととなっています
- [107] [CODE(HTML)@en[<[[meta]] [[http-equiv]]=[[Refresh]]>]] [SRC[HTML]]
- [108] [CODE(HTTP)@en[[[Refresh:]]]] [[ヘッダー]] [SRC[仕様なし]]
- [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[[バイト]]受信のいずれか遅い方で行わなければ[['''なりません''']]
- [189] [[allowed to show a popup]] の判定は[[利用者エージェント]]定義の時間枠で判断されます
-- <http://www.whatwg.org/specs/web-apps/current-work/#allowed-to-show-a-popup>
- [[XHR]] の [CODE(DOMa)@en[[[timeout]]]] は、毎[[ミリ秒]]新たに[[キュー]]に追加される[[マイクロタスク]]でチェックする形で仕様化されています。
-- 実装上は、指定されたタイムアウトまで[[ミリ秒]]単位で待って[[マイクロタスク]]を[[キュー]]に入れる形にできそうです。
- [CODE(DOMm)@en[[[getCurrentPosition]]]], [CODE(DOMm)@en[[[watchPosition]]]]
- [[アニメーション]] - [[レンダリングの更新]]参照
]FIG]
[214] [CODE(HTTP)@en[[[Retry-After:]]]] [[ヘッダー]]でも「待つ」時間の規定がありますが、
実装されていないと思われます。
* アイドル状態
[130] [[ブラウザー拡張]]や[[埋め込みブラウザー]]、他の[[アプリケーション]]から
[[Webブラウザー]]を制御する [[API]] などは、 [[Webページ]]の読み込みが終わり
「安定」した状態 ([[idle]] 状態) になったことを検知したい場合があります。
[EG[
[131] 例えば [[Webページ]]の表示が完了したら[[スクリーンショット]]を撮るソフトウェアの実装には、表示の完了のタイミングを知る必要があります。ここでいう表示の完了は、
必ずしも [[completely loaded]] ではなく、読み込み完了後に遅延して実行される[[スクリプト]]の完了も待ちたいです。
]EG]
[EG[
[132] [[Webアプリケーション]]の[[テスト]]のために外部から [[Webブラウザー]]を制御する場合、
[[クリック]]などの入出力操作を擬似的に発生させ、それに対する[[スクリプト]]の一連の動作が終わったら、
その時点の状態を確認したいかもしれません。
]EG]
[133] この状態は仕様上の概念ではありませんから ([[Webサイト]]の[[相互運用性]]には影響しません)、
判断方法はそれぞれの実装によります。一般的には、次のように判断するのが妥当でしょう。
[FIG(list)[
- [134] [[stops parsing]] ([[completely loaded]]) より後であり、 [CODE(JS)@en[[[document.open]]]] されていない
- [135] どの[[タスクキュー]]にも実行可能な[[タスク]]がない
- [136] [[マイクロタスク]]その他の実行可能な処理がない
- [138] 数秒以内に実行可能なタイマー ([CODE(DOMm)@en[[[setTimeout]]]] や
[CODE(HTTP)@en[[[Refresh]]]] など) がない
- [185] 実行中の [[fetch]] がない
- [205] 実行中の[[データベース取引]]がない
- [194] または、他の条件が満たされずとも、[[モーダルダイアログ]]の表示中である
]FIG]
[177] [[媒体]]の[[再生]]、[[アニメーション]]、[[ワーカー]]の実行、
[CODE(DOMi)@en[[[EventSource]]]] や [CODE(DOMi)@en[[[WebSocket]]]] などは、
無視するのが適当そうです。
[193] 無限に読み込みが続く場合や[[スクリプト]]により[[アニメーション]]する場合など、
この定義の「アイドル状態」に至らないこともあり得ます。
[217] [[ワーカー]]が [[protected worker]] でなくなるとは、
このアイドル状態に近いものを指しているようです ([[ワーカー]]の性質により、
本項での説明とは異なる点もあります)。
* 構文解析器との関係
[61] [[HTML]] の[[構文解析器]] [WEAK[(や、ちゃんと規定した仕様書が存在していませんが、 [[XML]] の[[構文解析器]])]]
は、それ自体は[[タスク]]の一部や全部ではなく、[[イベントループ]]とは概念として独立しています。
[62] [CODE(HTMLa)@en[[[innerHTML]]]] のように完全に[[タスク]]に含まれる処理の一部分として構文解析が実行されることもあれば、
[[fetch]] によって[[ネットワーク]]からデータを取得する度に順次生成されていく一連の[[タスク]]によって断続的に構文解析が進められることもあります。
[149] >>24 や >>59 の通り、[[構文解析]]によって[[イベントループ]]が[[スピン]]したり、[[字句化器]]がブロックされたりすることがあります。
* スクリプトとの関係
[201] [[スクリプト]]は他の[[スクリプト]]が実行されていることを直接観測できません [SRC[>>200]]。
実装上は複数の[[スクリプト]]が並列実行されている可能性はありますが ([[起源]]が異なる場合や[[ワーカー]]など)、
そのような[[スクリプト]]同士が通信する方法は [CODE(DOMm)@en[[[postMessage]]]]
など限られています。
;; [202] [[スクリプト]]の実行時間を計測したり、
サーバー側で何らかの情報交換を行ったりして間接的に他の[[スクリプト]]の動作を推測することはできるかもしれませんが。
[203] これによって[[著者]]は[[スレッド]]間のアクセス制御など複雑な処理を書かなくても済みます。
[[Webブラウザー]]は[[スクリプト]]が同時実行されないことを前提とした最適化を行えます
(がそれが制約となるケースもあるかもしれません)。
* 並列実行との関係
[43] いくつかの[[アルゴリズム]]は[[並列実行]]されます。すなわち、
[[イベントループ]]の動作中に同時に他の[[アルゴリズム]]が実行されていることがあります。
[47] [[並列実行]]されている[[アルゴリズム]]と[[イベントループ]]は、
[[同期区間]]により “[[join]]” されることがあります。
;; [72] 詳しくは[[並列実行]]と[[安定状態]]を参照してください。
* イベント・ループとの相互作用が不明なもの
[46] [[HTML]] 以前に規定されたものや、 [[HTML]] 以後であっても明確な仕様が存在しないものは、
[[イベント・ループ]]とどう相互作用するのか文書化されていません。
[45] [[XSLT]] の処理と[[イベント・ループ]]の関係は定義されていません。 [SRC[>>44]]
[145] [[Geolocation API]] は[[イベントループ]]が定義される前の仕様書なので関係が説明されていません。おそらく
- [CODE(DOMm)@en[[[getCurrentPosition]]]] や [CODE(DOMm)@en[[[watchPosition]]]] のアルゴリズムは非同期的に実行されます
- [[コールバック]]は[[タスク]]として追加されます (どの[[タスクキュー]]?)
- [CODE(DOMm)@en[[[watchPosition]]]] は非同期的に実行されているアルゴリズムを停止させます
[67] [CODE(HTMLe)@en[[[video]]]] や [CODE(HTMLe)@en[[[audio]]]] の再生の具体的なタイミングは規定されていません。
なお [CODE(HTMLe)@en[[[track]]]] の[[レンダリング]]は[[媒体要素]]の[[レンダリング]]に合わせて更新しなければならないと規定されています。
@@ [197] CODE(XMLe)@en[[[video]]]]/[CODE(XMLe)@en[[[audio]]]]
[196] [CODE(CSS)@en[[[aural]]]] や [CODE(CSS)@en[[[speech]]]] の[[レンダリング]]との関係は定義されていません。
[20] [[レンダリング]]に関わるものは、[[レンダリングの更新]]を参照。
* 原子的に実行されるべきもの
[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]] 版) <http://web.archive.org/web/20080828221023/http://www.whatwg.org/specs/web-workers/current-work/#queue>
]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]] 版))
<http://html5.org/tools/web-apps-tracker?from=6965&to=6966>
]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]] 版) <http://html5.org/tools/web-apps-tracker?from=7695&to=7696>
]REFS]
** セッション履歴イベントループ
[137] [[セッション履歴イベントループ]]は[[イベントループ]]が複数ある環境での履歴操作を記述するために2013年9月に導入されました。
;; [[セッション履歴イベントループ]]の項を参照。
** 安定状態
[REFS[
- [198] [CITE@en[Web Applications 1.0 r8620 Remove the 'stable state' logic from the 'pause' algorithm. Also, remove some examples that may soon become irrelevant.]] ([TIME[2014-05-09 03:12:00 +09:00]] 版) <http://html5.org/tools/web-apps-tracker?from=8619&to=8620>
]REFS]
**
[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]] 版))
<http://html5.org/tools/web-apps-tracker?from=7979&to=7980>
[109] [CITE[IRC logs: freenode / #whatwg / 20130701]]
( ([TIME[2013-07-02 23:22:48 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130701#l-216>
[110] [CITE@en[Bug 22522 – WebIDL, error handling, and promises]]
( ([TIME[2013-07-02 23:40:42 +09:00]] 版))
<https://www.w3.org/Bugs/Public/show_bug.cgi?id=22522>
[111] [CITE[IRC logs: freenode / #whatwg / 20130701]]
( ([TIME[2013-07-02 23:22:48 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130701#l-619>
[126] [CITE[IRC logs: freenode / #whatwg / 20130924]]
( ([TIME[2013-09-25 20:14:10 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130924>
[143] [CITE[IRC logs: freenode / #whatwg / 20131026]]
( ([TIME[2013-10-28 00:38:17 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20131026>
[144] [CITE[IRC logs: freenode / #whatwg / 20131030]]
( ([TIME[2013-11-01 21:16:51 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20131030#l-662>
[156] [CITE[IRC logs: freenode / #whatwg / 20140204]]
( ([TIME[2014-02-05 20:30:59 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20140204>
[157] [CITE[Add a warning sign for synchronous usage of the XMLHttpRequest API · 575999a · whatwg/xhr]]
( ([TIME[2014-02-13 06:44:19 +09:00]] 版))
<https://github.com/whatwg/xhr/commit/575999ae46afadc8f2ac6376c68fa7a887a88aa6>
[160] [CITE@en[Web Applications 1.0 r8510 Lay the groundwork for interruptible microtasks, mutation-observer style.]] ([TIME[2014-02-25 12:53:00 +09:00]] 版) <http://html5.org/tools/web-apps-tracker?from=8509&to=8510>
[175] [CITE@en[Web Applications 1.0 r8553 Make microtasks work in workers too, since eventually we'll want the JavaScript stuff to hook into this]] ([TIME[2014-03-19 03:12:00 +09:00]] 版) <http://html5.org/tools/web-apps-tracker?from=8552&to=8553>
[176] >>175 で[[ワーカー]]にも[[マイクロタスク]]が導入されました。
- [206] [CITE@en[Web Applications 1.0 r8630 Refactor 'stable states' to be defined in terms of microtasks]] ([TIME[2014-05-14 04:18:00 +09:00]] 版) <http://html5.org/tools/web-apps-tracker?from=8629&to=8630>
[215] [CITE@en[Web Applications 1.0 r8832 Hyperlink to 'step 1' of the event loop]]
( ([TIME[2014-10-10 06:39:00 +09:00]] 版))
<https://html5.org/r/8832>
[216] [CITE[IRC logs: freenode / #whatwg / 20141119]]
( ([TIME[2014-11-21 01:14:19 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20141119#l-819>
[52] 2014年11月には、[[レンダリングの更新]]処理と[[イベントループ]]との関係が明確化されました。
;; [[レンダリングの更新]]を参照。
[REFS[
- [73] [CITE@en[Web Applications 1.0 r8849 Flesh out how rendering happens in the event loop. This also defines requestAnimationFrame() and obsoletes the 'Timing control for script-based animations' spec (by request of that spec's editors)]] ([TIME[2014-11-20 06:56:00 +09:00]] 版) <https://html5.org/r/8849>
- [64] [CITE@en[Web Applications 1.0 r8850 Teach the event loop that it might not have a task to run]] ([TIME[2014-11-20 07:20:00 +09:00]] 版) <https://html5.org/r/8850>
]REFS]
* 関連
[12] [[イベント・ループ]]は、[[ストレージ・ミューテックス]]を所有することができます。
;; [39] [[ストレージ・ミューテックス]]は[[利用者エージェント]]全体で1つなので、
[[ストレージ・ミューテックス]]の解放待ちのために[[イベント・ループ]]全体がブロックされることがあります。
[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]] 版) <http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/>
@@ [83] [[IndexedDB]]
[77] [CITE@en[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'.]]
([TIME[2008-08-16 09:52:00 +09:00]] 版)
<https://html5.org/r/2074>
[78] [CITE@en[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'.]]
([TIME[2008-08-16 09:52:00 +09:00]] 版)
<https://html5.org/r/2074>
[79] [CITE@en[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'.]]
([TIME[2008-08-16 09:52:00 +09:00]] 版)
<https://html5.org/r/2074>
[FIG(quote)[
[FIGCAPTION[
[112] [CITE[IRC logs: freenode / #whatwg / 20150612]]
([TIME[2015-06-13 12:21:57 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20150612>
]FIGCAPTION]
> # '''['''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)
]FIG]
[113] [CITE[BlinkOn Scheduler Talk - Google スライド]]
([TIME[2015-06-25 18:40:21 +09:00]] 版)
<https://docs.google.com/presentation/d/1vqqBwDbnwrCz0P5JX_fxVQd0Q5KmVZdB_hk6RLNgO2Q/edit>
[219] [CITE[Surfin' Safari - Blog Archive » Introducing the Rendering Frames Timeline]]
([TIME[2015-09-09 11:13:22 +09:00]] 版)
<https://www.webkit.org/blog/3996/introducing-the-rendering-frames-timeline/>