走っているスクリプトの実行中断

スクリプトの中断 (JavaScript)

[4] スクリプトは、利用者または利用者エージェントにより、 実行途中で中断されることがあります。

仕様書

資源制限

[52] 利用者エージェントは、スクリプトに対して資源の制限を課して構いません。 例えば、CPU quotaメモリーの制限、合計実行時間の制限、帯域の制限などを課すことができます。 >>49

[53] スクリプトが制限を超えた時は、 QuotaExceededError 例外投げるか、 走っているスクリプトを中断するか、利用者に確認するか、スクリプトの実行に絞り弁 (throttele) を適用するかして構いません>>49

[13] ワーカーは、そもそも時間がかかったり高い負荷が予想されたりする処理のためのものなので、 より緩い制約とするべきかもしれません。

[15] 利用者エージェントは、ワーカーが制限に達したら、 ワーカーを殺す処理を実行して構いません >>14

スクリプト中断ダイアログ

[9] 多くの Webブラウザーは、資源制限に達した (あるいは達しそうな) ときに、 利用者にそのまま処理を継続するか、 走っているスクリプトの中断をするかの判断を求める (モーダルでない) ダイアログを表示します。

[10] このダイアログは、利用者が指示を出すか、状況が解消したら、閉じられます。

[11] 処理に時間がかかったり、 CPU 資源を多く消費したりすることが予測されるスクリプト著者は、 setTimeout などを使って処理を分割するのが普通です。 (タスクごとに実行されるスクリプトの実行時間からダイアログを出すか判断しているので、 複数のタスクに分割できれば回避できます。)

[12] ダイアログが出るほど長い時間を費やすようなスクリプトは、 Web互換でないというほどではありませんが、 (ダイアログ利用者を煩わせるという意味で、 あるいはそもそも負荷により利用者の操作を妨害するという意味で) 利用者に良い経験を提供できないものといえます。

[16] 利用者エージェントは、利用者ワーカーを殺すよう指示する手段を提供できます >>14

スクリプトの無効化

[51] 閲覧文脈スクリプトが有効スクリプトが無効の状態を有しており、 利用者エージェントの対応状況、利用者の設定、著者の指定によってどちらであるかが決定します。 スクリプトが無効の場合、スクリプトが作成されなかったり、スクリプトの実行が実際の内容に関わらず 「何もしない」となったり (>>28) します。詳しくはスクリプトが無効の項をご覧ください。

[54] スクリプトの実行中にスクリプトが無効になったときは、ただちにスクリプトを終端するべきです >>49

閲覧文脈、文書の中断

[19] 利用者エージェントは、 閲覧文脈を閉じるに当たりスクリプトを無効とする手段を利用者に提供できます >>49スクリプトが無効となると、実行中のスクリプトは中断されるので (>>54)、 言い換えると、閲覧文脈を閉じる時に実行中のスクリプトがあっても停止させることができます。

[17] 明文規定はありませんが、 navigate によって現在の文書の表示を破棄する際に、 走っているスクリプトの実行中断が行われる可能性があります。


[31] プラットフォーム (OS) やWebブラウザーの仕様により、 スリープ状態やアプリの切り替えなどで窓ごと破棄されたりタイマーが中断されたりすることがあります。

[32] いろいろな条件に左右されますし、観測しようとすることで挙動が変化する場合も想定されるので、 あくまで参考程度に。

[33] AndroidChromesetTimeout で数秒おきにサーバーにデータを送信させ、 放置してスリープ状態になるのを待つと、 1回目の試行では約2分半後に停止しており復帰させると Chrome は停止していました。 2回目の試行では約4分後に停止しており復帰させると Chrome で当該ページが開いた状態で未実行だった setTimeout も実行されました。

[34] iPhoneSafari で同じように試すと、 スリープ直後に停止しており復帰させると Safari で当該ページが開いた状態に復帰します。 setTimeout のタイマーがスリープ時間分一気に進むのか、 setTimeout で数秒待って送信して、の繰り返しが数回分一気に走ります。 (使っているのは setInterval ではない。) 他のアプリに切り替えている時、 Safari の他のタブに切り替えている時も同じように動作します。

[35] AndroidChrome は、 audio 再生中は中断を回避できます。

[36] iPhoneSafari も同様に中断を一応回避できます。 しかし他のアプリ次第でバックグラウンドでの再生が停止してしまいます。 Safari に切り替えると元の状態が復元されますが、再生停止されたものは戻らないようです。 さらに、スリープ状態に入ると、ループさせていてもループしないで再生停止してしまいます。 復帰した時少しだけ音が鳴りますが、途中で止まってしまい復元されたとはいえない状態です。 ループの途切れ目に他の音声が鳴っていれば次の周回に入りますw

ワーカーの中断

[68] ワーカーについては、ワーカーを殺す手順、 ワーカーを終端させる手順が規定されています。 両者は走っているスクリプトの実行中断を呼び出します。

それぞれの項を参照。

[18] ワーカーを終端させる手順は、 terminate メソッドによってワーカーの作成元のスクリプトから呼び出されることがあります。

[23] サービスワーカーを終端させる手順も参照。

走っているスクリプトの実行中断

[5] JavaScriptScriptEvaluation (古典スクリプトの実行から呼び出されます。) や Evaluation (モジュールスクリプトの実行から呼び出されます。) は、走っているスクリプトの実行中断 (abort a running script) >>49 により、結果を返さずに途中で中断されることがあります。

[7] 中断された場合、JavaScript実行文脈スタックを空にします。 finally があっても実行しません。 >>49

[6] これは HTML Standard では規定されていますが、 JavaScript の仕様書では明文化されていません >>49

[20] コールバック関数の呼び出しJavaScriptジョブの実行も、 同様に中断される可能性があります。

これはまだ明文化されていないようです (>>21 で言及はされていますが)。

[27] モジュールスクリプトの実行ModuleEvaluation走っているスクリプトの実行中断となった場合、 次の値を返します >>26

[28] Completion
Type
throw
Value
新しい QuotaExceededError DOMException
Target

[8] Gecko ではこれは catch できない (finally も実行されない) 特別な例外として実装されているようです。

[24] 中断は handle fetchInstall に影響を与えることがあります。

歴史

[3] ブラクラのような悪意あるスクリプトの濫用や、 悪意がなくても WebブラウザーOSの動作を不安定にする JavaScript アプリケーションから利用者を守るため、 00年代半ば頃から徐々にスクリプトの実行中断機能が Webブラウザーに実装されるようになってきました。

HTML5

[58] スクリプトを実行途中で実行時間の長さなどを根拠に中断しても良いことは HTML5 で明文化されました。

2016年改訂

[2] 2016年2月には、更に明確化が行われました。

[1] Fix #715: clarify how aborting a running script works · whatwg/html@6a48bfb ( 版) https://github.com/whatwg/html/commit/6a48bfbf1066034eab4786d62ba4017593c48430

[22] Web ビュー (Jwmsft著, ) https://msdn.microsoft.com/ja-jp/windows/uwp/controls-and-patterns/web-view

スクリプトを実行中にアプリが応答しないような場合があったとします。 すると、Web ビューが JavaScript 実行中に LongRunningScriptDetected イベントが発生し、スクリプトを中断する機会を提供します。 スクリプトがどれくらいの時間、実行されているのかを見るには、WebViewLongRunningScriptDetectedEventArgs の ExecutionTime プロパティを確認します。 スクリプトを停止するには、イベント引数の StopPageScriptExecution プロパティを true に設定します。 停止されたスクリプトは、以降の Web ビューのナビゲーションでもう一度読み込まれるまで、実行されません。

[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