* 仕様書

[REFS[
- [1] [CITE@en[Service Workers Nightly]] ([TIME[2017-03-02 15:00:14 +09:00]]) <https://w3c.github.io/ServiceWorker/#algorithms>
]REFS]

* ジョブ

[2] [DFN[[RUBYB[ジョブ]@en[job]]]]は、
[[サービスワーカー登録]]への要求を表します [SRC[>>1]]。

[29] [[ジョブ]]は実行オプションの集合体のようなもので、
実行は[[タスク]]として[[イベントループ]]内で行われます。

** 状態

[3] [[ジョブ][サービスワーカージョブ]]は、次の状態を持ちます。

[FIG(list members)[
: [DFN[[F[[RUBYB[[[ジョブ型]]]@en[job type]]]]]] :
[[登録][登録ジョブ]], [[更新][更新ジョブ]], [[登録解除][登録解除ジョブ]]のいずれか [SRC[>>1]]。
: [F[スクリプトURL][サービスワーカー]] :
: [F[ワーカー型]] :
: [F[キャッシュ利用]] :
: [F[クライアント][サービスワーカークライアント]] :
: [F[参照元]] :
: [F[ジョブ約束]] : [[約束]]または [CODE[null]]。初期値は [CODE[null]]。
: [DFN[[F[[RUBYB[[[等価ジョブ群のリスト]]]@en[list of equivalent jobs]]]]]] :
[[ジョブ][サービスワーカージョブ]]の[[リスト]]。初期値は[[空リスト]]。 [SRC[>>1]]
: [F[force bypass cache flag]] : 
]FIG]

** 等価性

[4] [[ジョブ][サービスワーカージョブ]]が[DFN[[RUBYB[等価]@en[equivalent]]]]であるとは、
次の条件を''すべて''満たすことをいいます [SRC[>>1]]。

[FIG(list)[
- [5] [F[ジョブ型]]が等しい
- [8] [F[適用範囲URL]]が等しい
- [6] [F[ジョブ型]]が[[登録][登録ジョブ]]または[[更新][更新ジョブ]]の場合、
-- [7] [F[スクリプトURL][サービスワーカー]]が等しい
]FIG]

** 作成

[12] [DFN[[RUBYB[ジョブ作成]@en[Create Job]]]]は、
[VAR[ジョブ型]]、
[VAR[適用範囲URL]]、
[VAR[スクリプトURL]]、
[VAR[約束]]、
[VAR[クライアント]]を次のようにします [SRC[>>1]]。

[FIG(steps)[
= [13] [VAR[ジョブ]]を、新しい[[ジョブ][サービスワーカージョブ]]に設定します。
[FIG(list members)[
: [F[ジョブ型]] : [VAR[ジョブ型]]
: [F[適用範囲URL]] : [VAR[適用範囲URL]]
: [F[スクリプトURL][サービスワーカー]] : [VAR[スクリプトURL]]
: [F[ジョブ約束]] : [VAR[約束]]
: [F[クライアント][サービスワーカークライアント]] : [VAR[クライアント]]
]FIG]
= [15] [VAR[クライアント]]が [CODE[null]] でない場合、
== [16] [VAR[ジョブ]]の[F[参照元]]を、[VAR[クライアント]]の[F[作成URL]]に設定します。
= [14] [VAR[ジョブ]]を返します。
]FIG]

[17] 次の場面で呼び出されます。

[FIG(list short)[
- [[登録開始]]
- [[ソフト更新]]
- [CODE[unregister]]
- [CODE[update]]
]FIG]

** ジョブ約束

[41] [[ジョブ][サービスワーカージョブ]]は、
[DFN[[F[[RUBYB[[[ジョブ約束]]]@en[job promise]]]]]]を持ちます。
値は[[約束]]または [CODE[null]]で、初期値は [CODE[null]] です。 [SRC[>>1]]

[42] [DFN[[RUBYB[ジョブ約束の解決]@en[Resolve Job Promise]]]]や[DFN[[RUBYB[ジョブ約束の拒絶]@en[Reject Job Promise]]]]は、
[VAR[ジョブ]]と[VAR[値]]について、次のようにします [SRC[>>1]]。

[FIG(steps)[
= [44] [VAR[ジョブ]]の処理を実行します。
= [45] [VAR[ジョブ]]の[F[等価ジョブ群のリスト]]の各[VAR[ジョブ]]について、
== [46] [VAR[ジョブ]]の処理を実行します。
]FIG]

[47] [VAR[ジョブ]]の処理は、次のようにします [SRC[>>1]]。

[FIG(steps)[
= [43] [VAR[ジョブ]]の[F[クライアント][サービスワーカークライアント]]が [CODE[null]] 以外の場合、
== [48] [[タスクをキューに追加]]します。
[FIG(list members)[
: [VAR[処理]] :
[FIG(steps)[
= [49] [VAR[ジョブ]]の[F[ジョブ約束]]を、[VAR[値]]で[[解決][約束の解決]]
([[ジョブ約束の解決]]の場合。) または[[拒絶]] ([[ジョブ約束の拒絶]]の場合。) します。
]FIG]
: [VAR[[[イベントループ]]]] : [VAR[ジョブ]]の[F[クライアント][サービスワーカークライアント]]の[F[有責イベントループ]]
: [VAR[[[タスク源]]]] : [[DOM操作タスク源]]
]FIG]
]FIG]

[50] 次の場面で呼び出されます。

[FIG(list short)[
- [[登録][登録ジョブ]]
- [[更新][更新ジョブ]]
- [[インストール][インストール (サービスワーカー)]] ([[解決][約束の解決]]のみ)
- [[登録解除][登録解除ジョブ]]
]FIG]

* ジョブキュー

[9] [DFN[[RUBYB[ジョブキュー][job queue]]]]は、
[[ジョブ]]を順に実行するための[[スレッド安全]]な[[キュー]]です。 [SRC[>>1]]

[10] [[FIFO]] [[キュー]]の一般的な特性を満たす[SHOULD[べきです]]。 [SRC[>>1]]

[11] [[利用者エージェント]]は、
[F[[[適用範囲URL]]から[F[ジョブキュー][サービスワーカージョブキュー]]への[[写像]]]]を持ちます。
[SRC[>>1]]

** スケジューリング

[18] [DFN[Schedule Job]] は、
[VAR[ジョブキュー]]と[VAR[ジョブ]]について、次のようにします [SRC[>>1]]。

[FIG(steps)[
= [19] [VAR[ジョブキュー]]が[[空][空リスト]]の場合、
== [20] [VAR[ジョブ]]を[VAR[ジョブキュー]]に [[push]] します。
== [21] [VAR[ジョブキュー]]について[[ジョブを走らせる]]処理を実行します。
= [22] それ以外の場合、
== [23] [VAR[最後のジョブ]]を、[VAR[ジョブキュー]]の末尾の項目に設定します。
== [24] [VAR[ジョブ]]が[VAR[最後のジョブ]]と[[等価][ジョブ等価]]で、
[VAR[最後のジョブ]]の[F[ジョブ約束]]が [[settle]] 済みでない場合、
=== [25] [VAR[ジョブ]]を[VAR[最後のジョブ]]の[F[等価ジョブ群のリスト]]に [[append]] します。
== [26] それ以外の場合、
=== [27] [VAR[ジョブ]]を[VAR[ジョブキュー]]に [[push]] します。
]FIG]

[28] 次の場面で呼び出されます。

[FIG(list short)[
- [[登録開始]]
- [[ソフト更新]]
- [CODE[unregister]]
- [CODE[update]]
]FIG]

** 実行

[30] [DFN[[RUBYB[ジョブを走らせる]@en[Run Job]]]]には、
[VAR[ジョブキュー]]について、次のようにします [SRC[>>1]]。

[FIG(steps)[
= [31] [[タスクをキューに追加]]します。
[FIG(list members)[
: [VAR[処理]] :
[FIG(steps)[
= [32] [VAR[ジョブ]]を、[[ジョブキュー]]の先頭の項目に設定します。
= [33] [[並列に]]、[VAR[ジョブ]]の処理を実行します。
]FIG]
: [VAR[[[タスク源]]]] : ?
]FIG]
]FIG]

;; [34] [[注記]]として[[登録][登録ジョブ]]や[[更新][更新ジョブ]]の[[タスクをキューに追加]]するのは
[CODE(DOMe)@en[DOMContentLoaded]] まで遅延する [SRC[>>1]] とありますが、
そのような[[規定]]は見当たりません。

[51] [VAR[ジョブ]]の実行とは、[F[ジョブ型]]により、
[VAR[ジョブ]]と[VAR[ジョブキュー]]について[[登録][登録ジョブ]]、
[[更新][更新ジョブ]]、[[登録解除][登録解除ジョブ]]の適切なものを実行することをいいます
[SRC[>>1]]。

[39] [[ジョブを走らせる]]処理は、[[Schedule Job]] と[[ジョブ終了]]から呼び出されます。

-*-*-

[35] [DFN[[RUBYB[ジョブ終了]@en[Finish Job]]]]は、
[VAR[ジョブ]]と[VAR[ジョブキュー]]について、
次のようにします [SRC[>>1]]。

[FIG(steps)[
= [36] [VAR[ジョブキュー]]から先頭の項目を [[pop]] します。
= [37] [VAR[ジョブキュー]]が[[空][空リスト]]でない場合、
== [38] [VAR[ジョブキュー]]の[[ジョブを走らせる]]処理を実行します。
]FIG]

[40] 次の場面で呼び出されます。

[FIG(list short)[
- [[登録][登録ジョブ]]
- [[更新][更新ジョブ]]
- [[インストール][インストール (サービスワーカー)]]
- [[登録解除][登録解除ジョブ]]
]FIG]
