/
712.txt
112 lines (82 loc) · 7.73 KB
/
712.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
[26] [[Webページ]]に [[navigate]] すると、読み込みがある程度進んだ時点で、
[[閲覧文脈]]に[DFN[レンダリングが開始]]されます。
* 仕様書
[REFS[
- [14] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#read-html>
- [16] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#update-the-session-history-with-the-new-page>
]REFS]
* 仕様上のタイミング
[15] [[navigate]] によって [[fetch]] が実行され、それを [[HTML]]
として処理することが決定されると、 [CODE(DOMi)@en[[[Document]]]]
が作られ、 [[HTML構文解析器]]と関連付けられます。
この [CODE(DOMi)@en[[[Document]]]] の作成よりは後であって、
しかし[[スクリプト]]の実行や、 [[stop parsing]] よりも前に、
[[update the session history with the new page]] が実行されることになっています [SRC[>>14]]。
どの[[要素]]が現れた後、といったような厳密なタイミングは規定されていません。
[17] [[update the session history with the new page]] は、
[CODE(DOMi)@en[[[Document]]]] を前の[[文書]]のものから >>15 の新しく作成したものに交換します
[SRC[>>16]]。
[18] [CODE(DOMi)@en[[[Document]]]] が交換されると、次の[[レンダリング]]の更新のタイミング
(明確に規定されているものに限れば、[[イベントループ]]中の[[レンダリング]]更新ステップの、
次の実行時) には、[[viewport]] に反映されることとなります。
[19] この [[update the session history with the new page]] は[[タスク]]をキューに入れることによって非同期的に実行されますし、
[[update the session history with the new page]] が行われる ([[構文解析]]に対する)
タイミングも厳密には決められていませんから、 [[Webブラウザー]]はそれぞれの好きなタイミングで新旧[[文書]]を入れ替えられることになります。
[21] ただし[[スクリプト]]実行前という制約があるので、
当該[[文書]]内の[[スクリプト]]が実行される時には、
必ず[[レンダリング]]が始まっていることになります。
他の[[文書]]の[[スクリプト]]からも、新しい [CODE(DOMi)@en[[[Document]]]]
にアクセスできるようになるタイミングと[[レンダリング]]が更新されるタイミングが >>18
の通り同時なので、[[レンダリング]]が始まる前の[[文書]]にアクセスすることはできません。
[22] 当該[[文書]]内の[[スクリプト]]は、
その実行時点で必ず[[レンダリング]]開始されていることになっているので、
どの時点から[[レンダリング]]が開始されていたか判定することはできません。
他の[[文書]]からは、 ([[レンダリング]]を直接観測することはできませんが)
[CODE(DOMi)@en[[[Document]]]] にアクセスして [[DOM]]
がどんな状態になっているか調べることで、どの状態から[[レンダリング]]が開始されたか推測はできます。
;; [23] [[スクリプト]]から観測可能なのに仕様上明確に定められていなくても大丈夫なのかと思うかもしれませんが、
元々ネットワークの状態により [[DOM]] が完成するまでの速度は違うものですから、
いつからアクセス可能になるかの厳密なタイミングに依存するような[[スクリプト]]が存在することは困難で、
明確に定義されなくても[[相互運用性]]上問題無いのでしょう。
[24] ただ、 [CODE(HTMLe)@en[[[iframe]]]] 内に [CODE(JS)@en[[[document.write]]]]
して [CODE(JS)@en[[[document.close]]]] するよりも前でいつ[[レンダリング]]が開始されるかのように、
[[利用者]]に観測可能な形で[[スクリプト]]の見た目上の動作が変わってしまうことが実際にあります。
[WEAK[(そのような [CODE(JS)@en[[[document.write]]]] の使い方は近年では稀ですが。。。)]]
[20] [[UI]] は仕様の対象外となっていますが、[[タイトルバー]]と [[viewport]]
で違う[[文書]]の情報を表示しているような状態が存在する実装は、仕様の趣旨に反しているかもしれません。
* [CODE(HTMLe)@en[[[head]]]] 要素注入
[12] [[Chrome]] と [[WinIE]] では、[[HTML]] [[構文解析器]]によって [CODE(HTMLe)@en[[[head]]]] [[要素]]が
[[DOM]] に挿入されるより''前に''[[スクリプト]]によって [CODE(HTMLe)@en[[[head]]]]
[[要素]]を挿入することが可能です。
[PRE(HTML example code)[
<html onclick="
var head = document.createElement ('head');
document.documentElement.appendChild (head);
">
]PRE]
[13] しかし、[[HTML]] [[構文解析器]]は必ず自動的に新しい [CODE(HTMLe)@en[[[head]]]] [[要素]]を挿入します。
>>12 による [CODE(HTMLe)@en[[[head]]]] [[要素]]が[[構文解析器]]に影響を与えることはありません。
(ですから、 [CODE(HTMLe)@en[[[head]]]] [[要素]]が2つになります。)
* 関連
[25] [[FOUC]] も参照。
* 歴史
[1] [[HTML]] の[[レンダリング]]の開始のタイミングと挙動をちょっと調べてみました。 [TIME[2010-11-13T05:09:51.200Z]]
;; <http://suika.fam.cx/~wakaba/-temp/test/html/head/>、
<http://suika.fam.cx/~wakaba/-temp/test/html/head/,cvslog>
** Firefox 3.6
- [2] [[HTML]] であることが確定した時点で(?)[[アドレスバー]]が切り替わります。
-- [[HTTP応答]]の[[本体]]の受信開始時点ではまだ切り替わりません。
-- [CODE(HTML)@en[[[<!DOCTYPE HTML>]]]] を受信したら切り替わりました。
- [3] [CODE(HTMLe)@en[[[title]]]] [[要素]]を受信した時点で[[タイトルバー]]が切り替わります。
- [4] [CODE(HTMLe)@en[[[body]]]] [[開始タグ]]を受信した時点で[[画布]]が切り替わります。
-- [CODE(HTMLe)@en[[[html]]]] や [CODE(HTMLe)@en[[[head]]]] に[[スタイル・シート]]で指定があったとしても、ここまでは[[レンダリング]]がはじまりません。
** Opera 9.52
- [5] [[HTTP応答]]の[[頭部]]を受信し終えた時点で[[アドレスバー]]、[[タイトルバー]]、[[画布]]が切り替わります。
- [6] [CODE(HTMLe)@en[[[body]]]] [[開始タグ]]を受信した時点で[[レンダリング]]がはじまります。
-- [7] [CODE(HTMLe)@en[[[html]]]] や [CODE(HTMLe)@en[[[head]]]] に[[スタイル・シート]]で指定があったとしても、ここまでは[[画布]]がまっさらになるだけで、本当の[[レンダリング]]ははじまりません。
** Chrome
- [8] [CODE(HTMLe)@en[[[html]]]] [[開始タグ]]を受信した時点で[[アドレスバー]]、[[タイトルバー]]、[[画布]]が切り替わります。
- [9] その後はインクリメンタルに[[レンダリング]]されていきます。
** WinIE8
- [10] [CODE(HTMLe)@en[[[body]]]] [[開始タグ]]を受信した時点で[[アドレスバー]]、[[タイトルバー]]、[[画布]]が切り替わります。
- [11] (リンクによるページ遷移ではなく) [[再読込]]の場合、再読込ボタンを押した時点で旧レンダリングへの[[イベント]]がスクリプトにわたらなくなります。 [CODE(HTMLe)@en[[[html]]]] [[開始タグ]]を受信した時点で新レンダリングで[[イベント]]を[[スクリプト]]が受け取れるようになります。 (再読込ボタンから [CODE(HTMLe)@en[[[html]]]] [[開始タグ]]までの間は観測する手段がない。)