window.onerror

エラー (DOM)

[107] Web においてスクリプトエラーは、 error イベントとして通知されます。このイベントが所定の手順で処理されない場合、 利用者に通知されます。

仕様書

エラーの処理

[108] スクリプトの構文解析の失敗やスクリプト内で例外が投げられてそれが catch されない場合など、スクリプトの処理中に検出されスクリプト内で直接処理されなかった失敗が本項でいうエラーです。

[109] エラーはまずエラーの報告手順に引き渡されて、 エラーを処理するために事前に登録されたスクリプトによって扱おうとします。

[110] そのようなスクリプトが存在しない場合や、処理できないとされる場合、 エラー処理中にエラーが発生した場合には、このエラーを利用者に報告することができます。

[141] この2つのステップをまとめたものが「例外を報告」です。 (「エラーを報告」と紛らわしいので注意。) しかし次に示す通り「例外を報告」 を呼び出さずに「エラーを報告」が直接呼び出される場合もあります。

[57] 仕様書上の手順としてエラーがどのように処理されるかは、 エラーが静的 (構文解析コンパイル等で検出されるエラー) か動的 (実行時エラー、 catch されない例外など) か、スクリプトが仕様書上どのように定義されているかによって異なります。

エラーがまずイベントとして報告され、 そこで取り扱われなかったら利用者 (開発者コンソール) に報告する、 という流れは共通ですが、細部が異なります。

[59] イベントハンドラーの静的エラーについては、 get the current value of the event handler 手順からエラーの報告手順が呼び出されます。 (イベントハンドラーの項を参照。)

[41] エラー取り扱われなかった場合、呼び出し元である >>58, >>59 から利用者エラーを報告して構わないとされています。

[76] ワーカーのスクリプトで catch されていないエラーが発生した時は、 WorkerGlobalScope対象としてエラーを報告しなければなりません。 それによってエラー取り扱われなかった場合は、次のようにします。 >>75

[77] 共有ワーカーの場合
開発者コンソールに報告して構いません>>76
[78] 専用ワーカーの場合
次のようなタスクタスクキューに追加します。
タスク
タスク源
DOM操作タスク源
処理
  1. [79] ワーカーに関連付けられた Worker オブジェクトにおいて ErrorEvent発火します。
  2. [86] >>79キャンセルされなければ、 Worker大域スコープにおいて catch されていない実行時エラーが発生したこととします。

[88] 従って専用ワーカーでのエラーは処理されなければ作成元をたどって結局最初の閲覧文脈に到達し、 そこから利用者へと通知されることになります。経路途中のワーカーが破棄されている場合は >>87 によりスキップされます。
[89] >>84 は適当な値がどのようなものか明確になっていませんが、元の ErrorEvent と同じ値でいいのでしょうか。 (たとえ起源が違っていたとしても、 postMessage によって通信できるワーカーからの情報なので、起源を超えた情報の漏洩には当たらないはずです。

[148] 開発者ツールコンソールから実行したスクリプトのエラーについてエラーの報告を呼び出すのは不適切でしょう。 ブラウザー拡張WebDriver 等により実行されたスクリプトのエラーも好ましくないと思われます。 しかし、それらがコールバックなどを登録し、それが通常の方法 (イベントdispatch など) により実行されるのであれば、そのエラーについては著者によるスクリプトのエラー同様にエラーの報告が行われることになります。

[149] ですから、著者はまったく想定しないエラーの報告を受ける可能性があります。

[58] かつては、スクリプトの作成手順によって作られるスクリプト (ほとんどのスクリプト) の静的エラーについては、 スクリプトの作成手順からエラーの報告手順が呼び出されていました。 現在はそこから呼び出されるコード入口点に飛ぶ手順から例外の報告が呼び出されています。

[62] Document と関連付けられたスクリプト捕捉されていない実行時エラーが発生した時は、 例外を報告しなければなりません >>61

[63] Document と関連付けられたスクリプトというのが曖昧ですが、 ワーカーではなく閲覧文脈内で実行されているスクリプトのことを指していると思われます。 しかし >>58>>59HTML 中で実行されるスクリプトはカバーされています。 この規定はそれ以外のイベントリスナーSVGスクリプトなどが対象なのでしょうか。

例外の報告

[16] スクリプトに関して例外を報告 (report the exception) する場合、 例外例外について、次のようにしなければなりません >>61

  1. [162] スクリプトを、関係するスクリプトに設定します。
  2. [165] エラーを、例外例外に設定します。
  3. [161] エラーの報告をします。
    スクリプト
    スクリプト
    エラー
    エラー
    スクリプトを含む資源における問題の位置
    対象
    スクリプト設定群オブジェクト大域オブジェクト
  4. [163] エラーが取り扱われなかった場合、
    1. [60] ワーカーの場合、 >>76 のようにします。
    2. [164] エラー開発者コンソールに報告して構いません。
[166] 関係するスクリプトや問題の位置の特定方法は明確ではありません。実装の品質の問題かもしれません。

[178] 例外の報告は、次の場面で行われることがあります。

エラーの報告

[157] エラーは、まず error イベントによって著者スクリプトに報告が試みられます。 その処理がエラーの報告です。

[12] エラーを報告 (report the error) >>13 する処理は、次の引数を受け取ります。

スクリプト (script)
スクリプトです。
エラー
報告するべき何らかのエラーです。
(line) (col)
エラーが発生した位置です。
対象 (target)
エラーを報告するイベント対象とするオブジェクトです。 大域オブジェクトが使われます。

[151] 次のようにしなければなりません >>13

  1. [14] 対象誤り報告モードなら、
    1. [152] エラーは取り扱われなかったとし、終わります。
  2. [15] 対象誤り報告モードに設定します。
  3. [21] スクリプトエラーミュートフラグが設定されていれば、
    1. [20] イベントを、新しい ErrorEvent に設定します。
      ErrorEvent
      [26] trusted
      [27] bubble
      [28] 取消可能
      [29] イベント型
      error
      [31] filename
      空文字列
      [23] lineno
      0
      [24] colno
      0
      [22] message
      Script error.
      [25] error
      null
  4. [30] そうでなければ、
    1. [17] エラー捕獲されなかった例外の場合、
      1. [156] エラーオブジェクトを、エラー例外に設定します。
    2. [18] それ以外で、エラーJavaScriptエラーの場合、
      1. [158] エラーオブジェクトを、エラーError オブジェクトに設定します。
    3. [19] それ以外なら、
      1. [160] エラーオブジェクトを、 null に設定します。
    4. [153] イベントを、新しい ErrorEvent に設定します。
      ErrorEvent
      trusted
      bubble
      取消可能
      イベント型
      error
      [32] filename
      スクリプトを得た元の資源URL記録URL直列化器を適用した結果
      [34] lineno
      [33] colno
      [36] message
      エラーを説明する利用者エージェント定義の文字列
      [35] error
      エラーオブジェクト
  5. [37] イベント対象において dispatch します。
  6. [38] 対象における誤り報告モードを終えます。
  7. [39] イベント取消されていれば、
    1. [154] エラー取り扱われたとします。
  8. [155] そうでなければ、
    1. エラー取り扱われなかったとします。

[40] 本手順を終えるとエラー取り扱われた (handled) 取り扱われなかった (not handled) かのいずれかとなります。

この2状態は、約束の拒絶と同様のものです。

[42] このエラーの報告対象となるオブジェクトは、大域オブジェクトです。 言い換えると大域オブジェクトエラーを報告するイベント対象オブジェクトとなります。 エラーを報告するイベントにより他のスクリプトが起動されることがあるので、 対象エラー報告モード (in error reporting mode) フラグを持っています。 エラーの報告によるイベント発火エラー報告モード中には行われません。

[43] つまり onerror 中のエラーによって onerror再帰的に呼ばれることはなく、 (利用者エージェント利用者エラーを報告するなら) 必ず利用者に報告されることになります。

エラーの位置

[44] ErrorEvent には filenamelinenocolno という属性があり、エラーが発生した元の位置の URL行番号列番号を表しています。

[45] HTML Standard は動的に作られた (document.write などによる) スクリプトであっても、また複数行にわたるイベントハンドラーなどであっても、 利用者エージェントががんばって位置を特定することをすすめています >>13。 しかしその具体的な方法は規定されておらず、実装の品質の問題であると考えられます。

エラーの起源

[46] 異なる起源資源スクリプトとして (script src などにより) 実行させることができますが、本来スクリプトではない資源を実行させ、 エラーメッセージなどからその資源の内容の一部または全部を取得したり、 推測したりすることができてしまうと異なる起源の情報の流出源となってしまうため、 同一起源方針によってエラーの報告は制限されています。

[47] スクリプトエラーミュート (muted errors) フラグ >>48 が設定されていると、 ErrorEvent によってエラーが発生した事実は伝えられますが、その内容や位置にはアクセスできなくなります (>>21)。

[50] エラーミュートフラグは、スクリプトの作成手順を呼び出す際に指定されていれば設定されます >>49。 これは次の場合に設定されます。

[56] 仕様書が存在しませんが、 SVG script 要素でも同様と思われます。

[54] つまり script 要素では CORS によって同一起源ポリシーを緩和できます。

ErrorEvent インターフェイス (DOM)

[65] ErrorEvent インターフェイスEvent インターフェイス継承したインターフェイスです。 >>64

[66] 他の Event と同様に、 ErrorEvent 構築子を使って実現値を得ることができます。引数としてはイベント型と、 省略可能で辞書 (EventInit を継承した ErrorEventInit) によって各種オプションを指定できます。 >>64

[67] ErrorEvent文書環境ワーカー環境の両方に晒されています >>64

メンバー

[68] ErrorEventEvent のメンバーに加えて次のメンバーを持ちます。 いずれも初期値は空文字列0null のいずれか適切なものです >>64

[74] 利用者エージェントによってdispatchされるイベントに関しては、これらの値は >>20, >>79 のようにして決定されます。

[177] filename IDL属性の値は通常 URL となります。 元の URL素片識別子が含まれていれば、そのままここに現れます >>171。 但し異なる起源のエラーの時は、空文字列になります。

onerror 属性 (DOM)

[99] GlobalEventHandlers インターフェイス >>91WorkerGlobalScope インターフェイス >>90onerror は、 error イベントに対応するイベントハンドラーIDL属性です。 IDL属性の型は OnErrorEventHandler です。

[98] OnErrorEventHandler >>92 は、 EventHandler とほぼ同じコールバック型ですが、引数として通常のイベントハンドラーのような Event 1つに加えて、 >>94 の場合も扱えるようになっています。

[101] HTML要素onerror 属性は、 error イベントに対応するイベントハンドラー内容属性です >>91

[102] body 要素frameset 要素では、 これらのイベントハンドラーIDL属性イベントハンドラー内容属性要素自身ではなく Window オブジェクトに対してのものとなります。

[103] error イベントエラーを報告するためのものと、 HTML要素などで用いられる通常のDOMイベントとしてのものの2種類があります。 onerror はそのどちらにも対応するイベントハンドラーであり、 >>98 の通り両方の形に対応していますし、次に示すように挙動も変わります。

[94] イベントハンドラー処理アルゴリズムイベントErrorEventイベントハンドラーIDL属性OnErrorEventHandler として定義されている場合に、 コールバックの呼び出し時の引数を次のようにします。 >>93

  1. message 属性値
  2. filename 属性値
  3. lineno 属性値
  4. colno 属性値
  5. error 属性値

[95] 他の場合には引数としては Event だけが渡されますが、 この場合は Event にはアクセスできません。

[96] イベントハンドラー処理アルゴリズムイベントErrorEventイベント型error の時に、コールバックが返した値が WebIDL booleanの値なら、イベントキャンセルします。 >>93

[97] 他の場合には逆にの値の時、キャンセルします。

[104] get the current value of the event handlerbody 要素frameset 要素onerror 内容属性の値を解釈するにあたり、 event, source, lineno, colno, error の5つの引数が順に与えられてるものとします。 >>106

[105] 他の場合には event のみとなります。

歴史

誕生

[129] onerrorJavaScript 1.1Window, Image, img 要素に追加されました >>128

[130] この頃はまだ try もありませんでしたから、エラーを回避する唯一の方法でした。
[131] body 要素にはまだなかったようです。

[132] この当時の定義では、初期値が undefined で、値を null にするとエラーを利用者に報告しない、となっていました。

[133] 当時の Netscape NavigatorJavaScript エラーを必ず新しいに表示する仕様でした。

[134] >>128 には

<IMG NAME="imageBad1" SRC="corrupt.gif" ALIGN="left" BORDER="2"
   onError="null">
... によって画像のエラーの表示を抑制できるとあります。現在の仕様や実装だとエラーは直接利用者には提示されませんし、 このように null を書いたところで抑制(?)できません。

[135] また img のエラーの通知を (個々の img に指定せずとも) window.onerror = null によって無効化できたようです >>128

標準不在の時代

[11] ryuzi_kambe の?D - onError="this.src=altimage"; ( 版) <http://d.hatena.ne.jp/ryuzi_kambe/20070221/p3>

[1] 第五章 クライアントサイドの技術:エラー処理 (try...catch) ( 版) <http://www.openspc2.org/JavaScript/Ajax/Ajax_study/chapter05/015/index.html>

このスクリプトが期待通り動作するのはInternet ExplorerとFirefoxのみです。Safari 2やOperaではwindow.onerrorの処理は無視されエラーが発生してしまいます。また、エラーメッセージやエラー行数に関しても Internet ExplorerとFirefoxでは内容が異なります(行数もカウント位置が違うため互換性がない)。

[2] JavaScript掲示板 ( 版) <http://otd8.jbbs.livedoor.jp/javascript/bbs_plain?base=14946&range=1>

ただし、Opera(私のは最新より1つバージョン古い)はwindow.onerrorをハンドリングできませんでした。

ボクが使っているOperaは8.5ですが、ハンドリングできました(^_^;A

私の環境では、onerrorからcallerをたどれるのはIEだけでした。

スタックトレースの取得は(以前かぱさんがしていたように)Exceptionコンストラクタの中でして、onerrorはそれがなかったとき補助的にした方がNetscape等もサポートできるはずです。

う~ん。私の環境(Mozilla1.7.12、Firefox1.5、Opera8.5、IE6.0、NN7.1)ではすべて取得できましたよ。 ただしOperaに関してだけは、エラーメッセージ中にスタックトレース情報が含まれていました。 また、NN(Mozilla系?)では、onerrorハンドラの第4引数に謎のスタックトレース情報が入ってきました! (今はそれを使わずに自分でcallerを使って取り直していますが…)

[3] うちの Opera 9.61 でも window.onerror は効かないみたいですが。

[6] 機密情報を含むJSONには X-Content-Type-Options: nosniff をつけるべき - 葉っぱ日記 ( ( 版)) <http://d.hatena.ne.jp/hasegawayosuke/20130517/p1>

HTML5

[114] Web Applications 1.0 (現在の HTML Standard) によって初めてエラーの報告の仕組みが詳細に記述されました。

[125] 最初に追加されたのは2004年8月28日のようです。 JavaScript 1.3 のドキュメントをもとにしていて >>124、現在に比べるとまだ単純な定義しかありませんでした。

[122] >>121 の2004年9月23日付けが、Internet Archive に残っている onerror の定義を含む最古のものです。 (当時はまだ svn で管理されていませんでした。)

[123] >>115 によって初期値が undefinednull によってエラーを抑制できるという伝統的な定義から、初期値が null で特に意味を持たない現在の定義に改められました。 >>126 によると当時の実装状況に追随したようです。

[127] >>125 の当時の実装状況がどうだったのか、気になります。

エラーイベントの拡張

[111] JavaScript 1.1 以来、なぜか URL行番号しかありませんでしたが、 2012年に列番号が追加されました。

[112] 2013年には、エラーのオブジェクト自体にもエラーイベントからアクセスできるように拡張されました。

DOM イベントとの統合

[113] 2013年にはエラーの報告も特別な仕組みとしてではなく、DOMイベントの特別な場合として発送される形に変更されました。

2013年以降

[150] CVE-2015-1729(fixed by MS15-065) - masa’s memo ( 版) <http://d.hatena.ne.jp/masa141421356/20150914/1442239071>

[168] Rewrite script execution on top of ES · whatwg/html@4891d18 ( 版) <https://github.com/whatwg/html/commit/4891d18aaf2df1d40aa61f467a5a10cfc19dd85d>

[169] Report errors to developer consoles, not users · whatwg/html@a6d04ea ( 版) <https://github.com/whatwg/html/commit/a6d04ea7652f5ad1b61e4ab95de490f51511bffe>

[172] Note that error events get canceled by returning true · whatwg/html@dcfc9bb ( 版) <https://github.com/whatwg/html/commit/dcfc9bb6f9d2a1018f0d55fea758c736bd28232e>

[173] 17713 – Exceptions thrown from event handlers should not be propagated ( 版) <https://www.w3.org/Bugs/Public/show_bug.cgi?id=17713>

[174] Editorial: define Event attribute defaults through IDL · whatwg/html@0be0229 ( 版) <https://github.com/whatwg/html/commit/0be02299f128cbb7c65a7ce259fdd838fd44a4b5>

[175] Clarify settings object, realm, and global relationships · whatwg/html@0866f1b ( 版) <https://github.com/whatwg/html/commit/0866f1b3f4b4ea5a99a30909e9bbe557dea0b460>

[176] Fix #301: detail how javascript: return values become response bodies by domenic · Pull Request #1107 · whatwg/html ( 版) <https://github.com/whatwg/html/pull/1107>

[139] Merge pull request #113 from domenic/modernize-invoke ( (bzbarsky著, )) <https://github.com/heycam/webidl/commit/09c011d8de1077fe5991ceded97838650e376f6c>

[159] Use USVString for all URLs ( (domenic著, )) <https://github.com/whatwg/html/commit/018b983b77b2cd908f6d00100e7e0abe893dd2c3>

[167] Change IDL for OnErrorEventHandlerNonNull from column to colno ( (zcorpan著, )) <https://github.com/whatwg/html/commit/4820c3cad60e8e55176b27d1e7249fc59ee9b22c>

[170] An exception is not always an object (e.g., throw 7) (annevk著, ) <https://github.com/whatwg/html/commit/6f32dc2cdbde1991dfa8ba2bf79a2eebe18324cd>

[171] Invoke the URL serializer for ErrorEvent.filename (zcorpan著, ) <https://github.com/whatwg/html/commit/2c8eef6d8901be84f41093a6f6758362cb413696>

[179] Clarify "report an exception" · Issue #958 · whatwg/html () <https://github.com/whatwg/html/issues/958>

[180] Fix event handler processing algorithm special cases (domenic著, ) <https://github.com/whatwg/html/commit/c065e991b65e10a1fc77ba77fed9f0822ff6858b>

[181] "Script error." message in window.onerror makes bad DevExp trade off · Issue #2440 · whatwg/html () <https://github.com/whatwg/html/issues/2440>

[183] Fix error cases of <script type=module> (domenic著, ) <https://github.com/whatwg/html/commit/115763124a641e8814665c5014d28155f95ff441>

[184] Remove more types from document.createEvent() (ayg著, ) <https://github.com/whatwg/dom/commit/5a532da58455e55b1e611161b72224d083fee7d4>