[2] [DFN[[RUBYB[ストレージミューテックス]@en[storage mutex]]]]は、
[[Webブラウザー]]が [[Cookie]] の書き込み等の[[競合状態]]の回避のために使う[[ミューテックス]]でした。

[42] 仕様上の概念としては存在していましたが、技術的問題から現実には実装されていませんでした。
[[競合状態]]を正しく処理する実装方法を用意するために仕様上は残されていましたが、
今後実装される見込みもないため、2015年末に削除されました。

* 仕様書

[REFS[
- '''[1] [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/#storage-mutex>'''
- [44] [CITE@en-US[Fetch Standard]] ([TIME[2014-02-07 15:59:32 +09:00]] 版) <http://fetch.spec.whatwg.org/#basic-fetch>
- [11] [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/#obtain-the-storage-mutex>
- [34] [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/#manually-releasing-the-storage-mutex>
- [33] [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/#threads>
- [37] [CITE@en-US[XMLHttpRequest Standard]] ([TIME[2012-11-14 13:48:01 +09:00]] 版) <http://xhr.spec.whatwg.org/#dom-xmlhttprequest-send>
]REFS]

* 処理モデル

[3] [[利用者エージェント]]は、[[ストレージ・ミューテックス]]を1つ持って[['''構いません''']]。
[[ストレージ・ミューテックス]]は、ある時点で
- [RUBYB[解放されている]@en[free]]
- 特定の[[イベント・ループ]]が[RUBYB[所有]@en[own]]している
- 特定の [[fetch]] 算法の[[実現値]]が[RUBYB[所有]@en[own]]している

... のいずれかの状態にあります。 [SRC[>>1]]

** イベントループによる所有

[10] [DFN[[RUBYB[ストレージ・ミューテックスを得る]@en[storage mutex]]]]場合は次のように処理しなければ[['''なりません''']]
[SRC[>>11]]。
[FIG[
= [12] 当該[[タスク]]の[[イベント・ループ]]が既に[[ストレージ・ミューテックス]]を所有しているなら、
これらの手順から抜けます。
= [13] そうでなければ、[[イベント・ループ]]が[[ストレージ・ミューテックス]]を取得できるまで[[一時停止]]します。
= [14] [[ストレージ・ミューテックス]]の所有権を取得します。
]FIG]

*** イベントループがストレージミューテックスを得る状況

[15] [[ストレージミューテックスの取得]]は次の状況で行われます。
[FIG(list)[
- [16] [CODE(JS)@en[[[document.cookie]]]] の読み書き
- [17] [CODE(HTMLa)@en[[[http-equiv]]]] が [CODE(HTTP)@en[[[Set-Cookie]]]] である [CODE(HTMLe)@en[[[meta]]]]
[[要素]]の処理
- [18] [CODE(DOMa)@en[[[localStorage]]]] の読み書き
]FIG]

;; [19] [CODE(DOMa)@en[[[sessionStorage]]]] の読み書きには[[ストレージミューテックス]]は関与しません。

;; [48] その他[[利用者エージェント]]依存のタイミングで[[クッキー]]を削除する場合
([[クッキー]]参照。) にも取得する必要がありそうです ([[イベントループ]]上の処理かどうかはわかりませんが...)。

** fetch 算法による所有

[20] [[ストレージ・ミューテックス]]は、 [[fetch]] 算法の中で [CODE(HTTP)@en[[[Set-Cookie:]]]]
の処理のために[[所有]]され、処理が終わり次第解放されます。

** 解放

[5] [[利用者エージェント]]は次の場合に[[ストレージミューテックス]]を[RUBYB[解放]@en[release]]しなければ[['''なりません''']]。
[FIG(list)[
- [6] [[スクリプト]]が[[プラグイン]]を呼び出した時 [SRC[>>1]]
- [7] [[プラグイン]]が[[スクリプト]]を呼び出した時 [SRC[>>1]]
- [21] [[fetch]] 内での処理が終わった時 (>>20)
- [22] [CODE(JS)@en[[[window.open]]]] [[算法]]の途中
- [23] [CODE(JS)@en[[[document.domain]]]] で新しい値が設定される時
- [24] [[navigate]] [[算法]]の途中
- [25] [[prompt to unload a document]] [[算法]]の途中
- [26] [[unload a document]] [[算法]]の途中
- [27] [[イベント・ループ]]で[[タスク]]を処理した直後
- [49] [[マイクロタスク]]を処理した直後
- [28] [CODE(JS)@en[[[alert]]]], [CODE(JS)@en[[[confirm]]]], [CODE(JS)@en[[[prompt]]]] の途中
- [29] [[printing steps]] [[算法]]の途中
- [30] [CODE(DOMm)@en[[[showModalDialog]]]] [[算法]]の途中
- [31] [CODE(JS)@en[[[navigator.yieldForStorageUpdates]]]]
- [32] [[run a worker]] [[算法]]の途中
- [38] [[XHR]] [CODE(DOMm)@en[[[send]]]] ([[同期フラグ]]が設定されている場合) [SRC[>>37]]
]FIG]

*** [CODE(JS)@en[navigator.yieldForStorageUpdates]]

[35] [DFN[[CODE(JS)@en[[[navigator.yieldForStorageUpdates]]]]]]
([CODE(DOMi)@en[[[NavigatorStorageUtils]]]] [[インターフェイス]]の
[CODE(DOMm)@en[[[yieldForStorageUpdates]]]] [[メソッド]]) が呼び出されると、
[[利用者エージェント]]は、そのメソッド呼び出しを行った[[タスク]]の[[イベント・ループ]]が[[ストレージ・ミューテックス]]を所有しているなら、
これを解放しなければ[['''なりません''']]。 [SRC[>>34]]

** 実装しない

[4] [[利用者エージェント]]は[[ストレージ・ミューテックス]]を実装しないことを選択しても構いません。
その場合、[[ストレージ・ミューテックス]]の取得や解放に関する要件は実装しなくて構いません。 [SRC[>>1]]

[8] [[ストレージ・ミューテックス]]を使わないと、あるサイトが複数の[[窓]]から同時に
[[Cookie]] や [[Web Storage]] にアクセスした時にデータが壊れる危険性があります。
しかし[[ストレージ・ミューテックス]]を使うと、ある[[サイト]]が [[Cookie]] や
[[Web Storage]] を使うと他のすべての[[サイト]]がブロックされてしまうことから、
[[Webブラウザー]]全体の[[パフォーマンス]]に大きく影響します。
[[Webブラウザー]]の実装者はこの2つの「evil」のどちらかを選択せざるを得ません。 [SRC[>>1]]

;; [9] これは [[Web Storage]] が失敗だったとされる理由の一つです。

[36] [[Web Storage]] の仕様上、[[スクリプト]]の実行途中に [CODE(DOMa)@en[[[localStorage]]]]
の値は (その[[スクリプト]]自身が予測できない形で) 変化することはない、とされています。 [SRC[>>33]]
しかし >>4 の通り[[ストレージ・ミューテックス]]を実装しないことを[[利用者エージェント]]が選択しているなら、
これは保証されません。

[43] 現実にはすべての [[Webブラウザー]]がこの方法を選択しています [SRC[>>41]]。
すなわち[[ストレージミューテックス]]は仕様上にしか存在しません。
通常は実装されない仕様は削除されるものですが、 [[HTML Standard]] の[[編集者]]である [[Ian Hickson]]
は、データが破壊される可能性がある実装しか認められないのは好ましくないとして、
[[ストレージミューテックス]]の仕様を残しています [SRC[>>40]]。

* 歴史

[REFS[
- [45] [CITE@en[Web Applications 1.0 r3705 Rename getStorageUpdates()]] ([TIME[2009-08-30 10:06:00 +09:00]] 版) <http://html5.org/tools/web-apps-tracker?from=3704&to=3705>
- [46] [CITE['''['''whatwg''']''' Storage mutex feedback]] ([TIME[2014-02-22 03:09:56 +09:00]] 版) <http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-August/022458.html>
- [39] [CITE[''''''[''''''whatwg'''''']'''''' localStorage, the storage mutex, document.domain, and workers]]
( ([TIME[2009-09-27 11:33:07 +09:00]] 版))
<http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2009-September/023059.html>
- [47] [CITE['''['''whatwg''']''' localStorage feedback]] ([TIME[2014-02-22 03:12:29 +09:00]] 版) <http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-December/024277.html>
- [40] [CITE[IRC logs: freenode / #whatwg / 20140213]]
( ([TIME[2014-02-14 20:43:39 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20140213#l-39>
- [41] [CITE@en[Web Applications 1.0 r8503 Add a note pointing out that browsers haven't implemented the storage mutex.]]
( ([TIME[2014-02-22 07:18:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=8502&to=8503>
]REFS]

** 削除

[50] [CITE@en[Remove the storage mutex due to lack of implementation · whatwg/html@1b918cf]]
([TIME[2015-12-16 14:49:18 +09:00]] 版)
<https://github.com/whatwg/html/commit/1b918cf72fcbba011f83b92ab5d1f483fb1cafa3>

[51] [CITE@en[Remove navigator.yieldForStorageUpdates() due to lack of implementation · whatwg/html@c6fb03d]]
([TIME[2015-12-16 14:53:13 +09:00]] 版)
<https://github.com/whatwg/html/commit/c6fb03dc3d9396f3a3c7f62b1c5cba1ed73cd9c5>

[52] [CITE@en[Fix #45: remove references to the storage mutex · whatwg/xhr@2529712]]
([TIME[2016-01-21 12:11:23 +09:00]] 版)
<https://github.com/whatwg/xhr/commit/25297128a14c543c909a052b2933d2b0b72550d1>

[53] [CITE@en[Fix #198: give precedence to custom Authorization headers · whatwg/fetch@9b18866]]
([TIME[2016-01-22 23:28:25 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/9b188662ab3d0319fe6e5fc10f034a9f10f7b069>