[4] スクリプトは、利用者または利用者エージェントにより、 実行途中で中断されることがあります。
[52] 利用者エージェントは、スクリプトに対して資源の制限を課して構いません。 例えば、CPU quota、メモリーの制限、合計実行時間の制限、帯域の制限などを課すことができます。 >>49
[53] スクリプトが制限を超えた時は、 QuotaExceededError
例外を投げるか、
走っているスクリプトを中断するか、利用者に確認するか、スクリプトの実行に絞り弁を適用するかして構いません。
>>49
[13] ワーカーは、そもそも時間がかかったり高い負荷が予想されたりする処理のためのものなので、 より緩い制約とするべきかもしれません。
[15] 利用者エージェントは、ワーカーが制限に達したら、 ワーカーを殺す処理を実行して構いません >>14。
[9] 多くの Webブラウザーは、資源制限に達した (あるいは達しそうな) ときに、 利用者にそのまま処理を継続するか、 走っているスクリプトの中断をするかの判断を求める (モーダルでない) ダイアログを表示します。
[10] このダイアログは、利用者が指示を出すか、状況が解消したら、閉じられます。
[11] 処理に時間がかかったり、 CPU 資源を多く消費したりすることが予測されるスクリプトの著者は、
setTimeout
などを使って処理を分割するのが普通です。
(タスクごとに実行されるスクリプトの実行時間からダイアログを出すか判断しているので、
複数のタスクに分割できれば回避できます。)
[12] ダイアログが出るほど長い時間を費やすようなスクリプトは、 Web互換でないというほどではありませんが、 (ダイアログで利用者を煩わせるという意味で、 あるいはそもそも負荷により利用者の操作を妨害するという意味で) 利用者に良い経験を提供できないものといえます。
[51] 閲覧文脈はスクリプトが有効、スクリプトが無効の状態を有しており、 利用者エージェントの対応状況、利用者の設定、著者の指定によってどちらであるかが決定します。 スクリプトが無効の場合、スクリプトが作成されなかったり、スクリプトの実行が実際の内容に関わらず 「何もしない」となったり (>>28) します。詳しくはスクリプトが無効の項をご覧ください。
[19] 利用者エージェントは、 閲覧文脈を閉じるに当たりスクリプトを無効とする手段を利用者に提供できます >>49。スクリプトが無効となると、実行中のスクリプトは中断されるので (>>54)、 言い換えると、閲覧文脈を閉じる時に実行中のスクリプトがあっても停止させることができます。
[17] 明文規定はありませんが、 navigate によって現在の文書の表示を破棄する際に、 走っているスクリプトの実行中断が行われる可能性があります。
[31] プラットフォーム (OS) やWebブラウザーの仕様により、 スリープ状態やアプリの切り替えなどで窓ごと破棄されたり、 タイマーが中断されたりすることがあります。
[32] いろいろな条件に左右されますし、観測しようとすることで挙動が変化する場合も想定されるので、 あくまで参考程度に。
[33]
Android の Chrome で setTimeout
で数秒おきにサーバーにデータを送信させ、
放置してスリープ状態になるのを待つと、
1回目の試行では約2分半後に停止しており復帰させると Chrome は停止していました。
2回目の試行では約4分後に停止しており復帰させると Chrome で当該ページが開いた状態で未実行だった
setTimeout
も実行されました。
[34]
iPhone の Safari
で同じように試すと、
スリープ直後に停止しており復帰させると Safari
で当該ページが開いた状態に復帰します。
setTimeout
のタイマーがスリープ時間分一気に進むのか、
setTimeout
で数秒待って送信して、の繰り返しが数回分一気に走ります。
(使っているのは setInterval
ではない。)
他のアプリに切り替えている時、
Safari の他のタブに切り替えている時も同じように動作します。
[35]
Android の Chrome は、
audio
再生中は中断を回避できます。
[36] iPhone の Safari も同様に中断を一応回避できます。 しかし他のアプリ次第でバックグラウンドでの再生が停止してしまいます。 Safari に切り替えると元の状態が復元されますが、再生停止されたものは戻らないようです。 さらに、スリープ状態に入ると、ループさせていてもループしないで再生停止してしまいます。 復帰した時少しだけ音が鳴りますが、途中で止まってしまい復元されたとはいえない状態です。 ループの途切れ目に他の音声が鳴っていれば次の周回に入りますw
[68] ワーカーについては、ワーカーを殺す手順、 ワーカーを終端させる手順が規定されています。 両者は走っているスクリプトの実行中断を呼び出します。
[18] ワーカーを終端させる手順は、 terminate
メソッドによってワーカーの作成元のスクリプトから呼び出されることがあります。
[23] サービスワーカーを終端させる手順も参照。
[5] JavaScript の ScriptEvaluation
(古典スクリプトの実行から呼び出されます。) や
Evaluation
(モジュールスクリプトの実行から呼び出されます。)
は、走っているスクリプトの実行中断
>>49 により、結果を返さずに途中で中断されることがあります。
[7] 中断された場合、JavaScript実行文脈スタックを空にします。
finally
があっても実行しません。 >>49
[6] これは HTML Standard では規定されていますが、 JavaScript の仕様書では明文化されていません >>49。
[20] コールバック関数の呼び出しやJavaScriptジョブの実行も、 同様に中断される可能性があります。
[27]
モジュールスクリプトの実行で ModuleEvaluation
が走っているスクリプトの実行中断となった場合、
次の値を返します >>26。
[8] Gecko ではこれは catch
できない
(finally
も実行されない) 特別な例外として実装されているようです。
[24] 中断は handle fetch や Install に影響を与えることがあります。
[3] ブラクラのような悪意あるスクリプトの濫用や、 悪意がなくても WebブラウザーやOSの動作を不安定にする JavaScript アプリケーションから利用者を守るため、 00年代半ば頃から徐々にスクリプトの実行中断機能が Webブラウザーに実装されるようになってきました。
[2] 2016年2月には、更に明確化が行われました。
[1] Fix #715: clarify how aborting a running script works · whatwg/html@6a48bfb ( 版) https://github.com/whatwg/html/commit/6a48bfbf1066034eab4786d62ba4017593c48430
[25] The WHATWG Blog — HTML and shared memory () https://blog.whatwg.org/html-and-shared-memory
[29] Fix error cases of <script type=module> (domenic著, ) https://github.com/whatwg/html/commit/115763124a641e8814665c5014d28155f95ff441
[30] Improve module instantiation/evaluation, especially around errors (domenic著, ) https://github.com/whatwg/html/commit/2b408b65a11fe76b6588b744e0ae74d30ff29b43