Google ChromeやNode.jsで利用可能なAPIです。Firefox等には搭載されていません。(まーあんまり使う場面なさそうですけど。)

以下、翻訳です。


All internal errors thrown in V8 capture a stack trace when they are created that can be accessed from JavaScript through the error.stack property. V8 also has various hooks for controlling how stack traces are collected and formatted, and for allowing custom errors to also collect stack traces. This document outlines V8’s JavaScript stack trace API.

V8で投げられたあらゆる内部エラーは、生成時のスタックトーレスを獲得します。これはJavaScriptのerror.stackプロパティを通してアクセス可能です。V8には他にも、スタックトレースの収集、書式化を制御する複数のフックや、カスタムエラーでスタックトレースを得るフックもあります。本文書はV8のJavaScriptスタックトレースAPIの概要です。

Basic stack traces – 基本的なスタックトレース

By default, almost all errors thrown by V8 have a stack property that holds the topmost 10 stack frames, formatted as a string. Here’s an example of a fully formatted stack trace:

ReferenceError: FAIL is not defined
   at Constraint.execute (deltablue.js:525:2)
   at Constraint.recalculate (deltablue.js:424:21)
   at Planner.addPropagate (deltablue.js:701:6)
   at Constraint.satisfy (deltablue.js:184:15)
   at Planner.incrementalAdd (deltablue.js:591:21)
   at Constraint.addConstraint (deltablue.js:162:10)
   at Constraint.BinaryConstraint (deltablue.js:346:7)
   at Constraint.EqualityConstraint (deltablue.js:515:38)
   at chainTest (deltablue.js:807:6)
   at deltaBlue (deltablue.js:879:2)

デフォルトでは、V8から投げられたほぼ全てのエラーはstackプロパティを持ち、上位10のスタックフレームを書式付き文字列の状態で格納しています。こちらが書式付きのスタックトレースの例です:

[javascript] ReferenceError: FAIL is not defined at Constraint.execute (deltablue.js:525:2) at Constraint.recalculate (deltablue.js:424:21) at Planner.addPropagate (deltablue.js:701:6) at Constraint.satisfy (deltablue.js:184:15) at Planner.incrementalAdd (deltablue.js:591:21) at Constraint.addConstraint (deltablue.js:162:10) at Constraint.BinaryConstraint (deltablue.js:346:7) at Constraint.EqualityConstraint (deltablue.js:515:38) at chainTest (deltablue.js:807:6) at deltaBlue (deltablue.js:879:2) [/javascript]

The stack trace is collected when the error is created and is the same regardless of where or how many times the error is thrown. We collect 10 frames because it is usually enough to be useful but not so many that it has a noticeable performance impact. You can control how many stack frames are collected by setting the variable

Error.stackTraceLimit

このスタックトレースは、エラーがどこで何度投げられたとしても、そのエラー生成時に収集されます。収集が10フレームに制限されているのは、一般にそれで十分であり、かつ知覚できるほどパフォーマンスに影響を与えないためです。もしスタックフレームの収集数を制御する必要があれば、この値を設定してください:

[javascript] Error.stackTraceLimit [/javascript]

Setting it to 0 will disable stack trace collection. Any finite integer value will be used as the maximum number of frames to collect. Setting it to Infinity means that all frames will be collected. This variable only affects the current context, it has to be set explicitly for each context that needs a different value. (Note that what is known as a “context” in V8 terminology corresponds to a page or iframe in Google Chrome). To set a different default value that affects all contexts use the

--stack-trace-limit <value>

command-line flag to V8. To pass this flag to V8 when running Google Chrome use

--js-flags="--stack-trace-limit <value>"

この値を0にすると、スタックトレースの収集を無効化する事ができます。有限整数であれば何でもフレーム収集数の上限値として設定可能です。Infinityを設定すると全てのフレームを収集するようになります。この設定は、設定時のコンテキストでのみ有効です。必要に応じて各コンテキストごとに異なる値を設定してください。(なおV8における「コンテキスト」という用語は、Google Chromeのページやiframeと合致します。) 全てのコンテキストで初期値と異なる値を用いる場合は、こちらのV8コマンドラインフラグを利用してください:

[javascript] –stack-trace-limit <value> [/javascript]

Google Chrome上のV8へ設定する場合はこちらのフラグです:

[javascript] –js-flags="–stack-trace-limit <value>" [/javascript]

Stack trace collection for custom exceptions – カスタムエラー用にスタックトレースを収集する

The stack trace mechanism used for built-in errors is implemented using a general stack trace collection API that is also available to user scripts. The function

Error.captureStackTrace(error, constructorOpt)

adds a stack property to the given error object that will yield the stack trace at the time captureStackTrace was called. The reason for not just returning the formatted stack trace directly is that this way we can postpone the formatting of the stack trace until the stack property is accessed and avoid formatting completely if it never is.

組み込みエラー向けのスタックトレースの仕組みは、ユーザースクリプトでも有効な汎用スタックトレース収集APIを用いて実装されています。以下の関数は、errorオブジェクトへstackプロパティを追加します:

[javascript] Error.captureStackTrace(error, constructorOpt) [/javascript]

なお、スタックトレースはcaptureStackTraceが呼ばれた時点のものになります。書式化済みのスタックトレースを直接返さない理由は、スタックトレースの書式化をstackプロパティへのアクセスまで待ち、不必要なら書式化の処理を省くためです。(訳者註:つまりcaptureStackTraceした瞬間にスタックトレースは記録されるものの、それを人が読める状態に変換する処理コストを省くため、書式化をgetterで遅延実行してるみたいです。)

The optional constructorOpt parameter allows you to pass in a function value. When collecting the stack trace all frames above the topmost call to this function, including that call, will be left out of the stack trace. This can be useful to hide implementation details that won’t be useful to the user. The usual way of defining a custom error that captures a stack trace would be:

function MyError() {
  Error.captureStackTrace(this, MyError);
  // any other initialization
}

省略可能なconstructorOpt引数には関数を与える事ができます。スタックトレース収集の際、ここで指定した関数と、より上位にある全てのフレームはスタックトレースから除外されます。これは利用者にとってはあまり意味のない実装の細かい部分を隠蔽するのに役立ちます。スタックトレースを取得するようなカスタムエラーの一般的な定義は、このようになるでしょう:

[javascript] function MyError() { Error.captureStackTrace(this, MyError); // 他の初期化処理 } [/javascript]

Passing in MyError as a second argument means that the constructor call to MyError won’t show up in the stack trace.

MyErrorを第2引数に指定する事で、スタックトレースにMyErrorの呼び出しを見せないようにする事ができます。

Customizing stack traces – スタックトレースのカスタマイズ

Unlike Java where the stack trace of an exception is a structured value that allows inspection of the stack state, the stack property in V8 just holds a flat string containing the formatted stack trace. This is for no other reason than compatibility with other browsers. However, this is not hardcoded but only the default behavior and can be overridden by user scripts.

例外のスタックトレースがstask stateをinspectionできるstructured value(訳註:ここら辺イミフ)であるJavaとは異なり、V8におけるstackプロパティは書式化済みスタックトレースの単純な文字列を保持しているだけです。これは他のブラウザーとの互換性のためでもあります。しかし、これはハードコーディングされていない初期動作であり、ユーザースクリプトで上書きする事ができます。

For efficiency stack traces are not formatted when they are captured but on demand, the first time the stack property is accessed. A stack trace is formatted by calling

Error.prepareStackTrace(error, structuredStackTrace)

and using whatever this call returns as the value of the stack property. If you assign a different function value to Error.prepareStackTrace that function will be used to format stack traces. It will be passed the error object that it is preparing a stack trace for and a structured representation of the stack. User stack trace formatters are free to format the stack trace however they want and even return non-string values. It is safe to retain references to the structured stack trace object after a call to prepareStackTrace completes so that it is also a valid return value. Note that the custom prepareStackTrace function is immediately called at the point when the error object is created (e.g. with new Error()).

効率化のためスタックトレースは取得された際は書式化されておらず、必要に応じて、つまりstackプロパティへの初回アクセス時に書式化されます。スタックトレースは次のコードが返したstackプロパティの値が使用されたとき書式化されます:

[javascript] Error.prepareStackTrace(error, structuredStackTrace) [/javascript]

Error.prepareStackTraceへ異なる関数値を与えた場合、その関数がスタックトレースを書式化するのに用いられます。 It will be passed the error object that it is preparing a stack trace for and a structured representation of the stack. (訳註:この一文よくわからず。”and”がどこにかかっているのやら。) ユーザー独自のスタックトレース書式化処理は自由に書式を設定する事ができ、文字列以外の値を返す事も可能です。有効な値を返すprepareStackTraceの呼び出しの後に構造化されたスタックトレースオブジェクトへの参照を保持しても安全です。独自のprepareStackTrace関数はエラーオブジェクトが生成された際、即時呼び出される事に注意してください。(例: new Error()

The structured stack trace is an Array of CallSite objects, each of which represents a stack frame. A CallSite object defines the following methods

  • getThis: returns the value of this
  • getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object’s [[Class]] internal property.
  • getFunction: returns the current function
  • getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function’s context.
  • getMethodName: returns the name of the property of this or one of its prototypes that holds the current function
  • getFileName: if this function was defined in a script returns the name of the script
  • getLineNumber: if this function was defined in a script returns the current line number
  • getColumnNumber: if this function was defined in a script returns the current column number
  • getEvalOrigin: if this function was created using a call to eval returns a CallSite object representing the location where eval was called
  • isToplevel: is this a toplevel invocation, that is, is this the global object?
  • isEval: does this call take place in code defined by a call to eval?
  • isNative: is this call in native V8 code?
  • isConstructor: is this a constructor call?

構築済みスタックトレースはCallSiteオブジェクトの配列で、それぞれが各スタックフレームを意味します。CallSiteオブジェクトは以下のメソッドが定義されています:

  • getThis: thisの値を返します。(訳注:実行コンテキストのthisの事。)
  • getTypeName: thisの型を文字列で返します。これはthisのコンストラクターの範囲で設定された関数の名前です。ない場合はオブジェクトの内部プロパティ[[Class]]になります。
  • getFunction: 現在の関数を返します。
  • getFunctionName: 現在の関数の名前を返します。一般的にはnameプロパティになります。nameプロパティがない場合、関数の文脈から推論します。 (訳者註:例えば無名関数をfnという変数へ代入して利用している場合、関数自体の名前(nameプロパティ)はありませんが、ここでは"fn"が得られます。なおメソッド名は後述のgetMethodNameで取得します。)
  • getMethodName: 現在の関数を保持しているthisないしprototypeのプロパティ名を返します。
  • getFileName: スクリプトファイル中にこの関数が定義されている場合、スクリプトファイルの名前を返します。
  • getLineNumber: スクリプトファイル中にこの関数が定義されている場合、現在の行番号を返します。
  • getColumnNumber: スクリプトファイル中にこの関数が定義されている場合、現在の列番号を返します。
  • getEvalOrigin: eval呼び出しによりこの関数が生成された場合、evalが呼ばれた場所を指すCallSiteオブジェクトを返します。
  • isToplevel: トップレベルで実行され、thisがグローバルオブジェクトか?
  • isEval: この呼び出しはeval呼び出しにより定義されたコードで実行されたか?
  • isNative: この呼び出しはV8のネイティブコードか?
  • isConstructor: これはコンストラクター呼び出しか?

The default stack trace is created using the CallSite API so any information that is available there is also available through this API.

デフォルトのスタックトレースは、CallSite APIを用いて生成されます。そこで得られる多くの情報はこのAPIを用いても取得可能です。

To maintain restrictions imposed on strict mode functions, frames that have a strict mode function and all frames below (its caller etc.) are not allow to access their receiver and function objects. For those frames, getFunction() and getThis() will return undefined.

strictモードの関数に課せられた制限(訳者註:関数から呼び出し元を参照できないようになっています)を遵守するため、strictモードの関数を持つフレームと下位の全フレーム(caller等)は、そのreceiver(訳者註:実行時コンテキストの事)と関数オブジェクトへのアクセスは禁じられています。これらのフレームでは、getFunction()getThis()undefinedを返します。

Compatibility – 互換性

The API described here is specific to V8 and is not supported by any other JavaScript implementations. Most implementations do provide an error.stack property but the format of the stack trace is likely to be different from the format described here. The recommended use of this API is

  • Only rely on the layout of the formatted stack trace if you know your code is running in v8.
  • It is safe to set Error.stackTraceLimit and Error.prepareStackTrace regardless of which implementation is running your code but be aware that it will only have an effect if your code is running in V8.

ここで紹介されたAPIはV8の仕様であり、他のJavaScript実装系ではサポートされていません。多くの実装系はerror.stackを提供していますが、スタックトレースの書式はここで紹介したものとは異なる可能性が高いでしょう。このAPIの推奨される使い方は、以下の通りです:

  • V8でのみ実行される事が分かっている場合、書式化済みスタックトレースのみに依存する
  • どの実装系でコードが実行されているかを考慮せずにError.stackTraceLimitError.prepareStackTraceを設定しても安全です。V8でのみ実行されている場合にのみ、意味を持ちます。

Appendix: Stack trace format – 付録: スタックトレースの書式

The default stack trace format used by V8 can for each stack frame give the following information:

  • Whether the call is a construct call.
  • The type of the this value (Type).
  • The name of the function called (functionName).
  • The name of the property of this or one of its prototypes that holds the function (methodName).
  • The current location within the source (location)

V8で利用されるデフォルトのスタックトレースの書式は、各スタックフレームに以下の情報を与えます:

  • コンストラクター呼び出しであるか。
  • thisの型。(Type)
  • 関数の名前。(functionName)
  • 関数を保持しているthisないし該当オブジェクトにおけるプロパティ名。(methodName)
  • ソースコード中の正確な位置。(location)

Any of these may be unavailable and different formats for stack frames are used depending on how much of this information is available. If all the above information is available a formatted stack frame will look like this:

at Type.functionName [as methodName] (location)

常に全ての情報があるとは限りません。各スタックフレームごとに書式が異なるのはどれだけの情報が有効であるかによります。前述の情報が全て有効である場合は、以下の書式でスタックフレームが出力されます:

[javascript] at Type.functionName [as methodName] (location) [/javascript]

or, in the case of a construct call

at new functionName (location)

コンストラクター呼び出しの場合は以下です:

[javascript] at new functionName (location) [/javascript]

If only one of functionName and methodName is available, or if they are both available but the same, the format will be:

at Type.name (location)

If neither is available will be used as the name.

functionNameとmethodNameのいずれかがある場合、あるいは両方あるものの同じである場合は、以下のように書式化されます:

[javascript] at Type.name (location) [/javascript]

どちらもない場合は名前としてが用いられます。

The Type value is the name of the function stored in the constructor field of this. In v8 all constructor calls set this property to the constructor function so unless this field has been actively changed after the object was created it it will hold the name of the function it was created by. If it is unavailable the [[Class]] property of the object will be used.

Typeはthisのコンストラクターの範囲で保持された関数の名前です。V8では、あらゆるコンストラクター呼び出しはこのプロパティ(訳註:nameの事か)をコンストラクター関数へ設定します。オブジェクト生成後に動的に変更されたとしても、関数名は生成時のものが保持されます。この値が無効な場合は内部プロパティ[[Class]]が利用されます。

One special case is the global object where the Type is not shown. In that case the stack frame will be formatted as

at functionName [as methodName] (location)

特殊ケースとして、グローバルオブジェクトにおいてはTypeが表示されません。その場合、以下の書式になります:

at functionName [as methodName] (location)

The location itself has several possible formats. Most common is the file name, line and column number within the script that defined the current function

fileName:lineNumber:columnNumber

locationは複数の書式が存在します。最も一般的なものは関数を定義するスクリプトのファイル名と行、列の番号です:

fileName:lineNumber:columnNumber

If the current function was created using eval the format will be

eval at position

現在の関数がevalで生成された場合はこの書式になります:

eval at position

where position is the full position where the call to eval occurred. Note that this means that positions can be nested if there are nested calls to eval, for instance:

eval at Foo.a (eval at Bar.z (myscript.js:10:3))

positionはevalが実行された場所です。これはevalが入れ子であれば、positionも入れ子になり得るという事にもなります。実例を挙げます:

eval at Foo.a (eval at Bar.z (myscript.js:10:3))

If a stack frame is within V8’s libraries the location will be

native

スタックフレームがV8のライブラリー内である場合は、locationはこうなります:

native

and if is unavailable it will be

unknown location

無効な場合はこうです:

unknown location

以上、翻訳終わり。