/
231.txt
322 lines (278 loc) · 20.9 KB
/
231.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
[8] [CODE(DOMi)@en[[[History]]]] [[インターフェイス]]の
[DFN[[CODE(DOMm)@en[[[go]]]]]] [[メソッド]]は、
[[結合セッション履歴]]上の移動を求めるものです。
[DFN[[CODE(DOMm)@en[[[back]]]]]] [[メソッド]]は前に1つ、
[DFN[[CODE(DOMm)@en[[[forward]]]]]] [[メソッド]]は先に1つ、
それぞれ移動を求めるものです。
[40] [DFN[[RUBYB[履歴の探索]@en[traverse the history]]]]は、
[[セッション履歴]]における移動を行う仕様書上の操作です。
* 仕様書
[REFS[
- [1] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#dom-history-go>
- [12] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#dom-history-back>
- [13] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#dom-history-forward>
- [21] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#traverse-the-history-by-a-delta>
- [11] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#history-notes>
- [42] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-04-25 04:40:19 +09:00]] 版) <https://html.spec.whatwg.org/#traverse-the-history>
]REFS]
* 呼び出し
[2] [CODE(DOMi)@en[[[History]]]] [[インターフェイス]]の
[DFN[[CODE(DOMm)@en[[[go]]]]]] [[メソッド]]は、次のように処理しなければ[['''なりません''']]
[SRC[>>1]]。
[FIG(steps)[
= [3] 第1引数を [CODE(IDL)@en[[[long]]]] として解釈します。省略されていれば、 0 とします。
= [4] [[文脈オブジェクト]]の関連付けられた[[文書]]が[[完全に活性]]でなければ、
[CODE(DOMe)@en[[[SecurityError]]]] [[例外]]を投げます。
= [5] そうでなければ、
== [6] 第1引数が 0 なら、 [CODE(JS)@en[[[location.reload]]]] [[メソッド]]のように処理します。
== [7] それ以外なら、第1引数の値を⊿として [[traverse the history by a delta]] を実行します。
]FIG]
[14] [CODE(DOMi)@en[[[History]]]] [[インターフェイス]]の
[DFN[[CODE(DOMm)@en[[[back]]]]]] [[メソッド]]は、次のように処理しなければ[['''なりません''']]
[SRC[>>12]]。
[FIG(steps)[
= [15] [[文脈オブジェクト]]の関連付けられた[[文書]]が[[完全に活性]]でなければ、
[CODE(DOMe)@en[[[SecurityError]]]] [[例外]]を投げます。
= [16] そうでなければ、⊿ = -1 として [[traverse the history by a delta]] を実行します。
]FIG]
[17] [CODE(DOMi)@en[[[History]]]] [[インターフェイス]]の
[DFN[[CODE(DOMm)@en[[[forward]]]]]] [[メソッド]]は、次のように処理しなければ[['''なりません''']]
[SRC[>>13]]。
[FIG(steps)[
= [18] [[文脈オブジェクト]]の関連付けられた[[文書]]が[[完全に活性]]でなければ、
[CODE(DOMe)@en[[[SecurityError]]]] [[例外]]を投げます。
= [19] そうでなければ、⊿ = +1 として [[traverse the history by a delta]] を実行します。
]FIG]
[35] [[利用者インターフェイス]]から[[利用者]]が履歴上の移動を指示したら、
[[traverse the history by a delta]] を適切な ⊿ の値で実行しなければ[['''なりません''']]
[SRC[>>21]]。
;; [36] 多くの [[Webブラウザー]]には[[メニューバー]]等で「[DFN[[[戻る]]]]」
や「[DFN[[[進む]]]]」の機能が実装されています。直前や直後だけでなく、
[[結合セッション履歴]]上の離れた位置に移動できるものもあります。
;; [37] [CODE(DOMm)@en[[[pushState]]]] の濫用を防ぐため、
直前ではなく前のページ (異なる[[文書]]の[[エントリー]]) に移動する方法をも提供するべきかもしれません
[SRC[>>11]]。
;; [38] [[利用者インターフェイス]]については[[履歴]]も参照。
[39] [[navigate]] は、最終的に[[履歴の探索]]を呼び出します。
* 差分指定による履歴の探索
[22] [DFN[traverse the history by a delta]] は、[RUBYB[差分]@en[delta]] ⊿
について処理を行う[[タスク]]を当該[[最上位閲覧文脈]]の[[セッション履歴探索キュー]]の末尾に追加することをいいます [SRC[>>21]]。
[FIG(steps)[
= [23] [[結合セッション履歴]]において[[現在エントリー]]の索引に ⊿ を加えた値が
0 [[未満]]か[[エントリー]]数[[以上]]となる時は、ここで停止します。
= [24] [[結合セッション履歴]]において[[現在エントリー]]の索引に ⊿ を加えた値が索引となる[[セッション履歴エントリー]]を得ます。
= [25] その[[セッション履歴エントリー]]の[[閲覧文脈]]を得ます。
= [26] その[[閲覧文脈]]の[[活性文書]]の [[unload a document]] を現在実行中なら、
ここで停止します。
= [27] 次のような[[タスク]]を[[タスクキュー]]に入れます。
[FIG(list members)[
[FIGCAPTION[
[[タスク]]
]FIGCAPTION]
:[[イベントループ]]:その[[閲覧文脈]]の[[活性文書]]の[[イベントループ]]
:[[タスク源]]:[[履歴探索タスク源]]
:処理:
[FIG(steps)[
= [28] その[[閲覧文脈]]を [VAR[[[navigate]] する[[閲覧文脈]]]]とする [[navigate]]
が実行中で [VAR[[[mature]]]] フラグが設定されていないなら、その [[navigate]]
を取り消します。
= [29] その[[閲覧文脈]]の[[活性文書]]が[[セッション履歴エントリー]]の[[文書]]と同じ[[文書]]でなければ、
== [30] [[全画面を完全に終了]]します。
== [31] その[[閲覧文脈]]の[[活性文書]]の [[prompt to unload a document]] を実行します。
== [32] [[refused to allow the document to be unloaded]] なら、停止します。
== [33] その[[閲覧文脈]]の[[活性文書]]の [[unload a document]] を実行します。
[VAR[recycle]] は[[偽]]とします。
= [34] その[[閲覧文脈]]において、[[セッション履歴エントリー]]へと[[履歴を探索]]します。
]FIG]
]FIG]
]FIG]
* エントリー指定による履歴の探索
[41] [VAR[[[セッション履歴エントリー]]]]を[[引数]]とする[DFN[[RUBYB[[[履歴の探索]]]@en[traverse the history]]]]は、次のようにしなければ[['''なりません''']] [SRC[>>42]]。
;; [43] 他に[[引数]]として、[VAR[[RUBYB[[[置換有効]]]@en[replacement enabled]]]]と
[VAR[non-blocking events]] フラグがあります。
後者のフラグは、[[素片識別子へのnavigate]]の時だけ[[真]]になります。
[FIG(steps)[
= [VAR[[[セッション履歴エントリー]]]]の[[文書]]が破棄されていれば、
== 次の通り[DFN[[RUBYB[エントリー更新]@en[entry update]]]]のための [[navigate]] を実行します。
[FIG(list members)[
:新しい[[資源]]の [[URL]]:[VAR[[[セッション履歴エントリー]]]]の [[URL]]
:新しい[[資源]]の[[要求メソッド]]:[VAR[[[セッション履歴エントリー]]]]の[[要求メソッド]]
:その他の[[引数]]:[VAR[[[セッション履歴エントリー]]]]の [[navigate]] の[[引数]]
([[始点閲覧文脈]]など)
:[[エントリー更新]]する[[エントリー]]:[VAR[[[セッション履歴エントリー]]]]
]FIG]
== ここで停止します。
= [[セッション履歴]]の[[現在エントリー]]の題名を
[CODE(DOMm)@en[[[pushState]]]]/[CODE(DOMm)@en[[[replaceState]]]] が設定していないなら
(= [[状態オブジェクト]]が存在し、[[題名]]が存在しないなら)、
== 題名を [CODE(JS)@en[[[document.title]]]] の値とします。
= 必要があれば、[[利用者エージェント]]が永続化させたい状態を[[セッション履歴]]の[[現在エントリー]]に反映させます。[[現在エントリー]]は[[持続的利用者状態付きエントリー]]となります。
= [[セッション履歴]]の[[現在エントリー]]と[VAR[[[セッション履歴エントリー]]]]とで[[文書]]が異なるなら、
== [[最上位閲覧文脈]]の[[文書族]]の[[文書]]に関連付けられた[[履歴探索タスク源]]の[[タスク]]を (あれば) 削除します。
== [VAR[[[セッション履歴エントリー]]]]の[[文書]]の[[文書の起源]]が[[セッション履歴]]の[[現在エントリー]]の[[文書]]の[[文書の起源]]と[[同じ起源]]でなければ、
=== [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]と[[同じ起源]]の[[文書]]と関連付けられており、[[セッション履歴]]の[[現在エントリー]]と連続するすべての[[セッション履歴エントリー]]に、
現在の[[閲覧文脈名]]を設定します。
=== [[セッション履歴]]の[[閲覧文脈]]が[[最上位閲覧文脈]]で、[[auxiliary browsing context]]
ではないなら、[[閲覧文脈名]]を未設定とします。
== [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]を、[VAR[[[セッション履歴エントリー]]]]の[[文書]]に設定します。
== [VAR[[[セッション履歴エントリー]]]]に[[閲覧文脈名]]があれば、
=== [[セッション履歴]]の[[閲覧文脈]]の[[閲覧文脈名]]をその名前とします。
=== [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]と[[同じ起源]]の[[文書]]と関連付けられており、[[セッション履歴]]の[[現在エントリー]]と連続するすべての[[セッション履歴エントリー]]で、[[閲覧文脈名]]を未設定とします。
== [VAR[[[セッション履歴エントリー]]]]の[[文書]]に [[autofill field name]]
が [CODE[[[off]]]] の[[フォーム制御子]]があれば、その[[再設定アルゴリズム]]を呼び出します。
== [VAR[[[セッション履歴エントリー]]]]の[[文書]]の[[現在文書準備度]]が
[CODE[[[complete]]]] なら、次のような[[タスク]]を[[キュー]]に追加します。
[FIG(list members)[
[FIGCAPTION[
[[タスク]]
]FIGCAPTION]
:[[タスク源]]:[[DOM操作タスク源]]
:処理:
[FIG(steps)[
= [[文書]]の [[page showing]] フラグが[[真]]なら、ここで停止します。
= [[文書]]の [[page showing]] フラグを[[真]]に設定します。
= [[セッション履歴文書可視性変更ステップ群]]を実行します。
= [[イベント]]を[[発火]]します。
[FIG(list members short)[
[FIGCAPTION[
[[イベント]]
]FIGCAPTION]
:[[イベント名]]:[CODE(DOMe)@en[[[pageshow]]]]
:[[インターフェイス]]:[CODE(DOMi)@en[[[PageTransitionEvent]]]]
:[[trusted]]:[[真]]
:[[対象]]:[[文書]]の [CODE(DOMi)@en[[[Window]]]]
:[[target override]]:[[文書]]
:[[bubbles]]:[[偽]]
:[[cancelable]]:[[偽]]
:[CODE(DOMa)@en[[[persisted]]]]:[[真]]
:[[既定動作]]:なし
]FIG]
]FIG]
]FIG]
== [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]の[[文書の番地]]を、
[VAR[[[セッション履歴エントリー]]]]の [[URL]] に設定します。
== [VAR[hash changed]] を[[偽]]にします。
= それ以外なら、
== [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]の[[文書の番地]]を、
[VAR[[[セッション履歴エントリー]]]]の [[URL]] に設定します。
== [VAR[[[セッション履歴エントリー]]]]と[[セッション履歴]]の[[現在エントリー]]とで
[[URL]] の[[素片識別子]]が異なるなら、
=== [VAR[hash changed]] を[[真]]にします。
=== [VAR[old URL]] を[[現在エントリー]]の [[URL]] にします。
=== [VAR[new URL]] を[VAR[[[セッション履歴エントリー]]]]の [[URL]] にします。
== それ以外なら、
=== [VAR[hash changed]] を[[偽]]にします。
= [49] [VAR[[[置換有効]]]]なら、[[セッション履歴]]において[VAR[[[セッション履歴エントリー]]]]の直前の[[セッション履歴エントリー]]を削除します。
= [57] [VAR[[[セッション履歴エントリー]]]]が[[持続的利用者状態付きエントリー]]でないなら、
== [58] [VAR[[[セッション履歴エントリー]]]]の [[URL]] に[[素片識別子]]があれば、
[[素片識別子にスクロール]]します。
= [VAR[[[セッション履歴エントリー]]]]が[[状態オブジェクト]]を持つなら、
[VAR[state]] を[[状態オブジェクト]]の[[構造化クローン]]とします。
それ以外なら、 [VAR[state]] を [[null]] とします。
= [[セッション履歴]]の[[閲覧文脈]]の[[活性文書]]の [CODE(DOMi)@en[[[History]]]]
[[オブジェクト]]の [CODE(JS)@en[[[history.state]]]] を [VAR[state]] に設定します。
= [VAR[[[セッション履歴エントリー]]]]の[[文書]]が[[最新エントリー]]を持ち、
それが[VAR[[[セッション履歴エントリー]]]]と異なるなら、 [VAR[state changed]]
を[[真]]に設定します。そうでなければ、 [VAR[state changed]] を[[偽]]に設定します。
= [VAR[[[セッション履歴エントリー]]]]の[[文書]]の[[最新エントリー]]を[VAR[[[セッション履歴エントリー]]]]に設定します。
= [66] [VAR[non-blocking events]] フラグが設定されていれば、次の通り処理する[[DOM操作タスク源]]の[[タスク]]を[[キュー]]に入れます。そうでなければ、次の通り処理します。
== [63] [VAR[state changed]] が[[真]]なら、
=== [64] 次の[[イベント]]を[[発火]]します。
[FIG(list members middle)[
[FIGCAPTION[
[[イベント]]
]FIGCAPTION]
:[[インターフェイス]]:[CODE(DOMi)@en[[[PopStateEvent]]]]
:[[イベント名]]:[CODE(DOMe)@en[[[popstate]]]]
:[[対象]]:[VAR[[[セッション履歴エントリー]]]]の[[文書]]の[CODE(DOMi)@en[[[Window]]]]
:[[bubbles]]:[[真]]
:[[取り消し可能]]:[[偽]]
:[[trusted]]:[[真]]
:[CODE(DOMa)@en[[[state]]]]:[VAR[state]]
:[[既定動作]]:なし
]FIG]
== [60] [VAR[[[セッション履歴エントリー]]]]が[[持続的利用者状態付きエントリー]]なら、
=== [61] [[持続的利用者状態の復元]]を行って構いません。
== [62] [VAR[hash changed]] が[[真]]なら、
=== [65] 次の[[イベント]]を[[発火]]します。
[FIG(list members middle)[
[FIGCAPTION[
[[イベント]]
]FIGCAPTION]
:[[インターフェイス]]:[CODE(DOMi)@en[[[HashChangeEvent]]]]
:[[イベント名]]:[CODE(DOMe)@en[[[hashchange]]]]
:[[対象]]:[[セッション履歴]]の[[閲覧文脈]]の[CODE(DOMi)@en[[[Window]]]]
:[[bubbles]]:[[真]]
:[[取り消し可能]]:[[偽]]
:[[trusted]]:[[真]]
:[CODE(DOMa)@en[[[oldURL]]]]:[VAR[old URL]]
:[CODE(DOMa)@en[[[newURL]]]]:[VAR[new URL]]
:[[既定動作]]:なし
]FIG]
= [68] 条件が満たされるなら、 [CODE[webNavigation]] API の [CODE[onHistoryStateUpdated]]
を呼び出します。
[VAR[[[遷移型]]]]と[VAR[[[遷移修飾子]]]]は適宜設定します。現在時刻も引き渡します。
= [69] [[セッション履歴]]の[[現在エントリー]]を[VAR[[[セッション履歴エントリー]]]]に設定します。
]FIG]
;; [44] [CODE(DOMm)@en[[[pushState]]]]/[CODE(DOMm)@en[[[replaceState]]]]
は必ず題名の値を設定するようですが...
;; [45] [[セッション履歴エントリー]]に基づき[[フォームデータ]]を復元する場合、
[[フォーム制御子]]の [CODE(HTMLa)@en[[[dir]]]] [[属性]]の値を変更することになるかもしれません [SRC[>>42]]。ということは [[mutation observer]] が呼び出されることになるかもしれません。
;; [46] [[素片識別子へのnavigate]]なら [VAR[non-blocking events]] フラグが設定されますから、
最後の2つの[[イベント]]は別の[[タスク]]で実行されることになります。
つまり[[現在エントリー]]が更新された後に[[イベント]]が[[発火]]されます。
それ以外の場合には、[[現在エントリー]]が更新される前に[[発火]]されることになります。
;; [47] 新しい[[活性文書]]が設定されてから新しい[[現在エントリー]]が設定されるまで、
最後の2つの[[イベント]]以外に[[スクリプト]]は実行されませんから、
[[スクリプト]]から観測可能な範囲で[[活性文書]]と[[現在エントリー]]の[[文書]]は常に同じです
([[現在エントリー]]の[[文書]]を直接的に観測する方法はありませんが)。
最後の2つの[[イベント]]が ([[同期的]]に) 実行されるのは[[素片識別子へのnavigate]]
の場合 (>>46) のみで、その場合は[[活性文書]]は変更されませんから、
[[現在エントリー]]は未更新ですが、[[現在エントリー]]の[[文書]]と[[活性文書]]は同じです。
;; [53] [[活性文書]]が変化すると、その[[文書]]が活性でなくなったことによって[[レンダリング]]その他の変化が
(おそらくは次の[[レンダリングの更新]]のタイミングで) 発生します。
[[活性文書]]を参照。
;; [54] [[閲覧文脈名]]は、[[履歴の探索]]の際に保存されたり復元されたりすることになっています。
[[閲覧文脈名]]は [CODE(HTMLa)@en[[[name]]]] [[属性]]の設定などによって変化することがあります。
* 置換有効フラグ
[48] [[履歴]]に関するいくつかの操作と [[navigate]] には、
[DFN[[VAR[[RUBYB[[[置換有効]]]@en[replacement enabled]]]]]]フラグがあります。
いくつかの[[メソッド]]はこのフラグを[[引数]]として指定できるほか、
このフラグに相当する2つの[[メソッド]]が用意されていることもあります。
いずれにせよ、[[履歴]]上で[[現在エントリー]]を置換して新しい[[セッション履歴エントリー]]とするべきか、[[現在エントリー]]の次のエントリーとするべきかを示すものです。
;; [CODE(JS)@en[[[document.open]]]] 以外では、最終的に >>49 に行き着きます。
[55] [CODE(JS)@en[[[window.open]]]] には「[VAR[[RUBYB[新しい]@en[new]]]]」
フラグがあって、 [[navigate]] の[[置換有効]]フラグとして使われるとともに、
[[初期「[CODE(URI)@en[about:blank]]」文書]]に関する分岐にも使われます。
[50] [[navigate]]/[[構文解析]]の最終段階である [[stops parsing]] で
[[completely loaded]] フラグが設定されるまでは、基本的には[[置換有効]]フラグが自動的に設定されます。
;; これは、 [CODE(JS)@en[[[location.href]]]] への[[代入]]などの [[JavaScript]]
による[[クライアント側]]の[[リダイレクト]]が行われた時に、[[リダイレクト]]ページを[[履歴]]から除去するためのものです。
[[JavaScript]] 実装初期の [[Webブラウザー]]はこの処理をしていなかったため、
[[利用者]]が[[戻る]]操作を行った時に[[リダイレクト]]ページに戻り、
直ちに自動的に[[リダイレクト]]されてしまい不便でした。
[51] [[初期「[CODE(URI)@en[about:blank]]」文書]]から最初の[[文書]]への
[[navigate]] でも、基本的に[[置換有効]]フラグが設定されます。そのため[[利用者]]や[[著者]]が想定していない空ページは[[履歴]]に現れなくなります。
[52] [CODE(HTTP)@en[[[Refresh]]]] による自動的な[[リダイレクト]]でも、
[[置換有効]]フラグが設定されます。
* 関連
[9] [CODE(JS)@en[[[history.go]]]] はあまり使われません。
[[結合セッション履歴]]上の他のエントリーの内容を[[スクリプト]]から調べることはできませんし、
[[入れ子閲覧文脈]]や [[Pjax]] を考慮して移動数を[[スクリプト]]から推測することも困難なので、
本メソッドは実用的ではありません。
[20] [CODE(JS)@en[[[history.back]]]] はしばしば「前のページに戻る」リンク・ボタンの実装に使われています。
[[著者]]としては簡単に実現できるメリットがありますが、
[[利用者]]としては[[検索エンジン]]など外部サイトから当該ページを表示した時に[[著者]]が想定していたであろうサイト内動線上の「前」のページを知ることができず、
不便であると批判もされています。
* 歴史
[59] [CODE(JS)@en[[[history.go]]]], [CODE(JS)@en[[[history.back]]]],
[CODE(JS)@en[[[history.forward]]]] は [[JavaScript 1.0]] で追加されました。
[10] [CITE[IRC logs: freenode / #whatwg / 20130923]]
( ([TIME[2013-09-24 20:37:19 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130923>
[56] [CITE@en[Make history.go() default to 0 · whatwg/html@a098b12]]
([TIME[2015-08-28 20:09:59 +09:00]] 版)
<https://github.com/whatwg/html/commit/a098b126b19733c74e60d302f0089b9064b8f77b>
[67] [CITE@en[Move scroll position restoration after popstate]]
( ([[domenic]]著, [TIME[2016-05-28 03:46:12 +09:00]]))
<https://github.com/whatwg/html/commit/98895af2179ad879da9fa57983ab9589251f7950>