JS Debugger API Guide

  • リビジョンの URL スラッグ: SpiderMonkey/JS_Debugger_API_Guide
  • リビジョンのタイトル: JS Debugger API Guide
  • リビジョンの ID: 372845
  • 作成日:
  • 作成者: yoshitanaka
  • 現行リビジョン いいえ
  • コメント

このリビジョンの内容

{{ jsapi_minversion_header("1.8.6") }}

{{ draft() }}

新しいJavaScript デバッガAPIはSpiderMonkey 1.8.6で紹介され、 JavaScriptのデバッグ機能の実装である古い版の JSDBGAPI よりも便利で使いやすいAPIとして提供されています。このAPIは、JavaScriptエンジンがデバッガを実装するために何をしているのか、コードを実行する際の進行状況をモニターするために、chromeコードから内部の状態をみることを許可するための必要な取りかかり口を提供します。コードの内容は利用できません。

Note: この新しいAPIは古い JSDBGAPI; に追加しています。一方のAPIを選択して使うべきですが、前提として、何の問題もなく両方のAPIを同時に使う事ができます。

デバッガにアクセスする

JSデバッガAPIにアクセスするために、JavaScriptコードモジュールをインポートする必要があります。それによって Debugger オブジェクトへアクセスできます。これは jsdebugger.jsm コードモジュールであり、以下のようにしてインポートすることができます:

Components.utils.import("resource://gre/modules/jsdebugger.jsm");

これが終了すると、大域的な Debugger コンストラクタによって提供されるJavaScript デバッガAPIにアクセスすることができます:

var myDebugger = new Debugger;

これはデバッグ用のターゲットなしに Debugger オブジェクトを生成します。仮にデバッグ用のターゲットを規定したいならば、そのコンパートメントがデバッグの対象となる一つ以上の 大域的 オブジェクトを規定します:

var myDebugger = new Debugger(object1, object2, object3);

デバッグの対象となるコンパートメントに{{ anch("大域的オブジェクト") }}を規定し、 Debugger.addDebuggee()を呼び出す事で、デバッグ対象となるコンパートメントを追加する事も可能です。

用語集

デバッガAPIドキュメントの中には、知っておく必要のある用語としていくつかの重要な用語があります。

Debuggee

A debuggee はデバッグの対象です。コンパートメントの中で動作するスクリプトの集まりです。

Debuggee values

A debuggee value 値は基本的な値であるか、Debugeeのコンパートメントの中にあるオブジェクトを参照する Debugger.Object のインスタンスです。

大域オブジェクト

SpiderMonkeyでは、 大域オブジェクト はスクリプトが動作する環境を提供する"囲われた庭"です。FireFoxでは各 DOMの {{ domxref("window") }} は、大域オブジェクトであり、その所有するすべての核となるJavaScriptオブジェクト (Object, Array, Function, Math, etc.)を持っています。これは、各ウィンドウ内のスクリプトに、他のタブやウィンドウのスクリプトに影響する事なしに、これらのオブジェクトを操作させます。

大域オブジェクトとそのすべての内容は単一の コンパートメント の中にあります。観念的に、現段階で強制されていることではありませんが、各コンパートメントは単一の大域オブジェクトを含みます。

デバッグ実行時、観察したい一つ以上の大域オブジェクトを選択し、そしてあなたが関心を持っているスクリプトのデバッグ情報を受け取るだけです。

インボケーション関数

インボケーション関数 は デバッガAPI内のどの関数にもあり、デバッグするためのスクリプト内で、 Debugger.Object.prototype.call()Debugger.Frame.prototype.eval()のようなコードを呼び出します。

インボケーション関数の操作による一般的な処理手続きは、以下のようになります:

  1. スタック上の older(より古い)フレームを最も最新のデバッグ用フレームにし、存在しないならば null にします。これは二度とデバッガが所有するフレームの一つにはなりません。
  2. スタック上にステップ1で決定したようにolder属性を持つ"debugger"型の Debugger.Frame をプッシュします。
  3. 適当なインボケーション関数を使用して、それが継続できるようにdebuggeeフレームを設定してdebuggeeコードを呼び出します。例えば、 Debugger.Frame.prototype.eval()を呼び出す場合、"eval"フレームが動作するコード上にプッシュされ、 Debugger.Object.prototype.call() は”call”フレームをプッシュします。
  4. デバッガが完了したときに(正常に戻ったか、例外を投げたか、強制終了したかに関わらず)デバッガフレームをポップし、インボケーション関数からデバッガに適当な 完了値 を戻します。

参照

参照 普通は Debugger.Object インスタンスである、他のオブジェクトによってオブジェクトが参照されることです。

デバッグオブジェクトの検査

デバッガAPIは、デバッグ対象内で値の変更と検査をするためのメソッドを提供します。

Debugger.DebuggeeWouldRun 例外

デバッガの完全な状態を保全するために、デバッガはあなたにデバッグ対象のデータ、そのデータはデバッグ対象がコードを動かすことを必要とする原因になるかもしれないデータ、へのアクセスを行わせません。代わりに、デバッガはDebugger.DebuggeeWouldRun 例外のインスタンスを投げます。

これが発生した場合のいくつかの例では以下の事例を含みます:

  • 大域で取得する側を走らせ、変数を読み込みます。
  • 命令のオペランド 変数を読み込みます。
  • オブジェクトがプロキシオブジェクト(これはトラップのハンドラを走らせます)の属性記述子を取得します。

特別な目的を持つ関数だけが、デバッグ対象のコードを走らせることを許されています; {{ anch("インボケーション関数") }}と呼ばれるものです。その他の操作では、 Debugger.DebuggeeWouldRun 例外をなげて、デバッグ対象のコードを動作させます。

デバッグ対象のフレーム

デバッグ対象内の各スタックフレームは、正確に一つの Debugger.Frame のインスタンスにより表されている。デバッグ対象が固有のフレーム内で動作している間、呼び出されるすべての取りかかり口となるオブジェクトのメソッドは、同じフレームオブジェクトを受け取ります。同様に、スタックを移動して以前にアクセスされたデバッグ対象のスタックフレームに戻ることは、以前と同じフレームオブジェクトを取得する事です。デバッガは追加の属性をフレームオブジェクトに付け足すことができ、それらを後見つけることを要求します。これに加えて、二つの命令が同一のフレームを参照しているかどうかを判断するために、 == オペレータを使う事ができます。

デバッグ対象がスタックフレームをポップするとき、例えば、-- 関数呼び出しが戻ったり、例外が投げられたような理由で -- Debugger.Frame のインスタンスが参照しているフレームは非アクティブになります。あなたは属性の有効性を調べることでこれを検出することができます。仮にこの属性が偽である場合、フレームは非アクティブになります。それは、その他の属性と例外を投げるすべてのメソッドが対象になります。

Note: デバッガが信頼できるとき: --デバッグ対象が動作しているかまたは、スタックそれ自身からフレームを取り除くとき-- にだけ、フレームは非アクティブになります。

デバッガはデバッグ対象とJavaScriptスタックを共有しますが、 Debugger.Frame によってデバッガに提供されているスタックフレームは、デバッガ固有のコードが動作するフレームを含む事はありません。

Note: ジェネレータ- iterator(繰り返し処理に使います。以前の処理結果を保持し次の計算に渡します)オブジェクトを操作している状態に対応したスタックフレームは、特別な種類の Debugger.Frameを使う事に相当します。

ジェネレータフレーム

SpiderMonkeyはジェネレータ-iteratorオブジェクトをサポートしています。関数や命令の実行時に繰り返す事で中断する変数群を提供します。例えば、 yield() オペレータを用いた関数呼びだしは、ジェネレータ- iterator オブジェクトを提供します。そして、 (各 i の値に対して  i * i (ここで i [1, 2, 3 ]))のような命令を実行して数値を求めます。

ジェネレータ - iterator オブジェクトは、固定の継続したフレームなしにスタックフレームを参照します。ジェネレータのコードが動作している間、その繰り返し処理では、 next() メソッド(ジェネレータが次の結果を要求する)を呼び出すフレームは対象になります。ジェネレータが中断している間は、特別の継続処理用のフレームはありません。そして、それが再開したとき、再開のための継続処理フレームは以前の再開処理時のフレームとは異なっています。

ジェネレータフレームと他のフレームとの相違

ジェネレータフレームに相当する Debugger.Frame のインスタンスは、通常のスタックフレームとは以下の点で異なっています:

  • generator の属性が真
  • older 属性は、 ジェネレータが動作している間はフレームの継続処理フレームを参照し、ジェネレータが中断している間は null を参照します。
  • depth 属性は、処理が再開したときはスタック内のフレームの位置を反映し、ジェネレータ中断中は null を表します。
  • live 属性は、フレームが戻るか、例外を投げるか、強制終了するまで真のままの状態を維持します。それは、スタックの上に存在しない間でもジェネレータのフレームは有効であることを意味しています。
  • ジェネレータフレームは、ジェネレータが値を分離し、処理が中断する各段階で消えてなくなります。ジェネレータが次の値を生み出すために再開するときに、スタックの最上位に再び現れます。同じ Debugger.Frame インスタンスは、それが戻るか、例外を投げるか、終了するまでジェネレータフレームを参照します。
Note: ジェネレータが再開するとき、スタック上にある Debugger.Frame オブジェクトは、新しいオブジェクトか、特定されていないすでにあるオブジェクトかに関わりません。この点で固有の動作に関して信頼すべきではありません。

如何にジェネレータフレームと他のフレームが同じになるか

すべての他の Debugger.Frame メソッドと属性にアクセスするものは、ジェネレータフレームが中断する時であっても、他の種類のフレームで動作します。あなたは、例えば、そのとき中断させた yield()オペレーションを監視するために scriptoffset 属性を使って、ジェネレータフレームの属性を検査することができます。

ジェネレータフレームの生存期間

Debugger.Frame インスタンスがジェネレータ - iteratorフレームを参照するために、ジェネレータ- iteratorオブジェクトへのしっかりした参照を保持してます。フレームとそのオブジェクトは、Debugger.Frame インスタンスと同じ長さの有効期間を持っています。 しかし、一旦、ジェネレータ関数が戻るか、例外を投げるか、終了すると、 Debugger.Frame のインスタンスは非アクティブになり、 live 属性は偽となり、その他の種別のフレームはポップされます。

一旦ジェネレータフレームが無効になると、ジェネレータ - iteratorオブジェクトへのしっかりした参照はもはや保持されません。

例外処理

例外をほどく

例外が投げられた後、(例外発生時の処理状態等の情報を積み上げた)スタックをほどく必要があります。これは、ハンドラーがその例外を見つけて、スタックからフレームを取り除く処理になります。各フレームがほどく処理の間に至まで、SpiderMonkeyはフレーム内の現在のオフセットが 、投げられた例外を処理するための例外ハンドラーがあることを示している try ブロックの中にあれば、そのオフセットを注視します。もしそうであれば、操作はその例外に一致している catch/finally コードへジャンプします。さもなくば、フレームは破棄され、スタックをほどく処理を続けます。

デバッガAPI はデバッガに、フレームをほどく処理の間、各デバッガのスクリプトフレームのために、 Debugger.onExceptionUnwind() メソッドを呼び出すことによって、例外処理の間中スタックをほどく処理をモニターさせます。メソッドはいかに処理の実行が進行するのかを示す、 再開するための値(resumption value) を戻します。

スクリプト

各 JSAPI JSScript オブジェクトは Debugger.Script インスタンスに対応しています。そのインスタンスはデバッグ対象内のバイトコードの処理手続きを参照します。それは、以下のような種別の JSScript オブジェクトからコードを表します:

  • 関数のボディ、これは関数内のすべてのコードですが、ネストされた関数内のコードは含みません。
  • コードは単一の eval()呼び出しに渡されます。そのコードによって定義される関数のボディはふくみません。
  • {{ HTMLElement("script") }} 要素の内容
  • HTMLに組み込まれているか、他のJavaScriptコードによって要素に添付されているDOMのイベントハンドラ。
  • URL内に javascript: として表示されるコード。

どのようにDebugger.Scriptsは生成されるか

Debugger インターフェイスは、存在するスクリプトオブジェクトを見つけるように、 Debugger.Script オブジェクトを生成します。デバッガコードは、スクリプトオブジェクトに所有する属性を追加することができます。これが起こるにはいくつかの方法があります。例えば:

  • 取りかかり口であるオブジェクトメソッド Debugger.onNewScript() を呼び出す事。
  • Debugger.Frame.script 属性値の変更。
  • Debugger.Object.functionScript() メソッドを呼び出す事。
  • スクリプトを変更するかもしれないその他の機構。

The Debugger インターフェイスは、正確に個別の原スクリプトオブジェクトの Debugger.Script インスタンスを生成します。デバッガコードは、後で見つけて参照できるように、所有する属性をスクリプトオブジェクトに追加することができます。単純に二つの記号表示が同じスクリプトを参照しているかどうかを決めるのに == オペレータを使う事ができます。

A Debugger.Script インスタンスは、 JSScript オブジェクトへのしっかりとした参照を保持しています。それによって、ガーベージコレクション処理により回収されることからスクリプトを保護します。しかし、 eval() に渡されるコードに相当するスクリプトは、 eval() が戻ったときに削除されます。そのため、あなたはスクリプトがデバッグ対象として存在しているかどうかを判断するために live 属性の値を検査すべきです。

Note: SpiderMonkeyは、同じ Debugger.Script インスタンスを複数の関数、あるいは、同じ構文解析環境で実行される同じソースファイル内の同じ位置にある同じソースコードに対応したコードセグメントを計算します。

オブジェクト

A Debugger.Object インスタンスはデバッグしているスクリプト内のオブジェクトに対応しています。デバッガコードはデバッグ対象となるオブジェクトへは直接アクセスしません。代わりに Debugger.Object インスタンスによってデバッグ対象となるオブジェクトを操作し、変更し、参照します。

Debugger.Object インスタンスは反応指向(reflection-oriented)なメソッドを持っています。それは参照しているオブジェクト変更、検査させます。あなたは、参照している属性にアクセスするために、 Debugger.Object.getOwnPropertyDescriptor()Debugger.Object.defineProperty() のようなメソッドを使うことができます。これはデバッガが、そのデバッグ対象の属性を見るときに、不注意にデバッグ対象内のgetter や setter を呼び出すこのとないよう確認します。

SpiderMonkeyは正確に デバッグ対象内の各オブジェクトのに対する一つの Debugger.Object インスタンスを生成します。もし、デバッガが複数の経路を経て(二つの関数が同じオブジェクトを呼び出すときのような)、同じオブジェクトに出くわす場合、毎回、同じ Debugger.Object のインスタンスが存在します。 これはデバッグ対象内で二つの Debugger.Object インスタンスが同じオブジェクトを参照しているときに、それを認識する為に == のようなオペレータを使う事ができることを意味しています。そして、デバッグ対象のオブジェクトに関するあなた固有のメタデータを保存する為に、あなた固有の属性をDebugger.Object インスタンスに追加することができます。

多くの Debugger.Object インスタンスは、 デバッグ対象の動作と状態をデバッガに明らかにする間、SpiderMOnkeyによって生成されます。デバッガそれ自身は、デバッグ対象のコンパートメント内にオブジェクトを生成するために、 Debugger.Object.copy()Debugger.Object.create() を使います。

Debugger.Object インスタンスは、ガーベージコレクションから回収対象として参照されることからオブジェクトを保護します。 Debugger.Object インスタンスが有効である限り、それが参照するものも同様に有効なもとして残ります。このように、ガーベージコレクションは、Debugger.Object のインスタンスに対してデバッガから見える影響はありません。

如何に値はデバッガとデバッグ対象の間で渡されるか

デバッガが安全にオブジェクトと値をデバッグ対象のコンパートメント内で検査、変更することを支援するために、 Debugger インターフェイスは以下の慣例に従います。:

  • 基本的な値は、デバッガとデバッグ対象の間で自由に渡されます。それらの値でコピーとラッピングが必要となるものは、透過的に取り扱われます。
  • デバッグ対象から受け取るオブジェクトは、DOM要素のようなホストオブジェクトを保持します。それは、 Debugger.Object のインスタンスとしてデバッガに含まれています。それらの参照を検査するために反応指向(reflection-oriented) メソッドを提供します。
  • デバッガオブジェクトが所有する Debugger.Object インスタンスだけがデバッグ対象に渡す事ができます。これが起きるとき、デバッガはDebugger.Objectそれ自身ではなく、 Debugger.Object の参照を受け取ります。

以下も参照して下さい

このリビジョンのソースコード

<p>{{ jsapi_minversion_header("1.8.6") }}</p>
<p>{{ draft() }}</p>
<p>新しいJavaScript デバッガAPIはSpiderMonkey 1.8.6で紹介され、 JavaScriptのデバッグ機能の実装である古い版の <a href="/en/JSDBGAPI_Reference" title="JSDBGAPI Reference">JSDBGAPI</a> よりも便利で使いやすいAPIとして提供されています。このAPIは、JavaScriptエンジンがデバッガを実装するために何をしているのか、コードを実行する際の進行状況をモニターするために、chromeコードから内部の状態をみることを許可するための必要な取りかかり口を提供します。コードの内容は利用できません。</p>
<div class="note">
  <strong>Note:</strong> この新しいAPIは古い <a href="/en/JSDBGAPI_Reference" title="JSDBGAPI Reference">JSDBGAPI</a>; に追加しています。一方のAPIを選択して使うべきですが、前提として、何の問題もなく両方のAPIを同時に使う事ができます。</div>
<h2 id="Getting_access_to_the_Debugger">デバッガにアクセスする</h2>
<p>JSデバッガAPIにアクセスするために、JavaScriptコードモジュールをインポートする必要があります。それによって <code>Debugger</code> オブジェクトへアクセスできます。これは <code>jsdebugger.jsm</code> コードモジュールであり、以下のようにしてインポートすることができます:</p>
<pre class="plain">
Components.utils.import("resource://gre/modules/jsdebugger.jsm");
</pre>
<p>これが終了すると、大域的な <code>Debugger</code> コンストラクタによって提供されるJavaScript デバッガAPIにアクセスすることができます:</p>
<pre>
var myDebugger = new Debugger;
</pre>
<p>これはデバッグ用のターゲットなしに <code>Debugger</code> オブジェクトを生成します。仮にデバッグ用のターゲットを規定したいならば、そのコンパートメントがデバッグの対象となる一つ以上の <strong> 大域的 </strong> オブジェクトを規定します:</p>
<pre>
var myDebugger = new Debugger(object1, object2, object3);
</pre>
<p>デバッグの対象となるコンパートメントに{{ anch("大域的オブジェクト") }}を規定し、 <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#addDebuggee()" title="en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#addDebuggee()"><code>Debugger.addDebuggee()</code></a>を呼び出す事で、デバッグ対象となるコンパートメントを追加する事も可能です。</p>
<h2 id="Glossary">用語集</h2>
<p>デバッガAPIドキュメントの中には、知っておく必要のある用語としていくつかの重要な用語があります。</p>
<h3 id="Debuggee">Debuggee</h3>
<p>A <strong>debuggee</strong> はデバッグの対象です。コンパートメントの中で動作するスクリプトの集まりです。</p>
<h3 id="Debuggee_values">Debuggee values</h3>
<p>A <strong>debuggee value</strong> 値は基本的な値であるか、Debugeeのコンパートメントの中にあるオブジェクトを参照する <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> のインスタンスです。</p>
<h3 id="Global_object">大域オブジェクト</h3>
<p>SpiderMonkeyでは、 <strong>大域オブジェクト</strong> はスクリプトが動作する環境を提供する"囲われた庭"です。FireFoxでは各 DOMの {{ domxref("window") }} は、大域オブジェクトであり、その所有するすべての核となるJavaScriptオブジェクト (<a href="/en/JavaScript/Reference/Global_Objects/Object" title="Object"><code>Object</code></a>, <a href="/en/JavaScript/Reference/Global_Objects/Array" title="Array"><code>Array</code></a>, <a href="/en/JavaScript/Reference/Global_Objects/Function" title="Function"><code>Function</code></a>, <a href="/en/JavaScript/Reference/Global_Objects/Math" title="Math"><code>Math</code></a>, etc.)を持っています。これは、各ウィンドウ内のスクリプトに、他のタブやウィンドウのスクリプトに影響する事なしに、これらのオブジェクトを操作させます。</p>
<p>大域オブジェクトとそのすべての内容は単一の <a href="/en/SpiderMonkey/SpiderMonkey_compartments" title="en/SpiderMonkey/SpiderMonkey_compartments"> コンパートメント </a>の中にあります。観念的に、現段階で強制されていることではありませんが、各コンパートメントは単一の大域オブジェクトを含みます。</p>
<p>デバッグ実行時、観察したい一つ以上の大域オブジェクトを選択し、そしてあなたが関心を持っているスクリプトのデバッグ情報を受け取るだけです。</p>
<h3 id="Invocation_functions">インボケーション関数</h3>
<p><strong>インボケーション関数</strong> は デバッガAPI内のどの関数にもあり、デバッグするためのスクリプト内で、 <code>Debugger.Object.prototype.call()</code> や<code>Debugger.Frame.prototype.eval()</code>のようなコードを呼び出します。</p>
<p>インボケーション関数の操作による一般的な処理手続きは、以下のようになります:</p>
<ol>
  <li>スタック上の <code>older</code>(より古い)フレームを最も最新のデバッグ用フレームにし、存在しないならば <code>null</code> にします。これは二度とデバッガが所有するフレームの一つにはなりません。</li>
  <li>スタック上にステップ1で決定したようにolder属性を持つ"debugger"型の <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame" title="Debugger"><code>Debugger.Frame</code></a> をプッシュします。</li>
  <li>適当なインボケーション関数を使用して、それが継続できるようにdebuggeeフレームを設定してdebuggeeコードを呼び出します。例えば、 <code>Debugger.Frame.prototype.eval()</code>を呼び出す場合、"eval"フレームが動作するコード上にプッシュされ、 <code>Debugger.Object.prototype.call()</code> は”call”フレームをプッシュします。</li>
  <li>デバッガが完了したときに(正常に戻ったか、例外を投げたか、強制終了したかに関わらず)デバッガフレームをポップし、インボケーション関数からデバッガに適当な <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Completion_values" title="Completion values">完了値</a> を戻します。</li>
</ol>
<h3 id="Referent">参照</h3>
<p><strong>参照 </strong> 普通は <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> インスタンスである、他のオブジェクトによってオブジェクトが参照されることです。</p>
<h2 id="Inspecting_debuggee_objects">デバッグオブジェクトの検査</h2>
<p>デバッガAPIは、デバッグ対象内で値の変更と検査をするためのメソッドを提供します。</p>
<h3 id="The_Debugger.DebuggeeWouldRun_exception">Debugger.DebuggeeWouldRun 例外</h3>
<p>デバッガの完全な状態を保全するために、デバッガはあなたにデバッグ対象のデータ、そのデータはデバッグ対象がコードを動かすことを必要とする原因になるかもしれないデータ、へのアクセスを行わせません。代わりに、デバッガは<code>Debugger.DebuggeeWouldRun</code> 例外のインスタンスを投げます。</p>
<p>これが発生した場合のいくつかの例では以下の事例を含みます:</p>
<ul>
  <li>大域で取得する側を走らせ、変数を読み込みます。</li>
  <li>命令のオペランド<a href="/en/JavaScript/Reference/Statements/with" title="with"><code>と</code></a> 変数を読み込みます。</li>
  <li>オブジェクトがプロキシオブジェクト(これはトラップのハンドラを走らせます)の属性記述子を取得します。</li>
</ul>
<p>特別な目的を持つ関数だけが、デバッグ対象のコードを走らせることを許されています; {{ anch("インボケーション関数") }}と呼ばれるものです。その他の操作では、 <code>Debugger.DebuggeeWouldRun</code> 例外をなげて、デバッグ対象のコードを動作させます。</p>
<h2 id="Debuggee_frames">デバッグ対象のフレーム</h2>
<p>デバッグ対象内の各スタックフレームは、正確に一つの <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame" title="Debugger"><code>Debugger.Frame</code></a> のインスタンスにより表されている。デバッグ対象が固有のフレーム内で動作している間、呼び出されるすべての取りかかり口となるオブジェクトのメソッドは、同じフレームオブジェクトを受け取ります。同様に、スタックを移動して以前にアクセスされたデバッグ対象のスタックフレームに戻ることは、以前と同じフレームオブジェクトを取得する事です。デバッガは追加の属性をフレームオブジェクトに付け足すことができ、それらを後見つけることを要求します。これに加えて、二つの命令が同一のフレームを参照しているかどうかを判断するために、 <code>==</code> オペレータを使う事ができます。</p>
<p>デバッグ対象がスタックフレームをポップするとき、例えば、-- 関数呼び出しが戻ったり、例外が投げられたような理由で -- <code>Debugger.Frame</code> のインスタンスが参照しているフレームは非アクティブになります。あなたは属性の有効性を調べることでこれを検出することができます。仮にこの属性が偽である場合、フレームは非アクティブになります。それは、その他の属性と例外を投げるすべてのメソッドが対象になります。</p>
<div class="note">
  <strong>Note:</strong> デバッガが信頼できるとき: --デバッグ対象が動作しているかまたは、スタックそれ自身からフレームを取り除くとき-- にだけ、フレームは非アクティブになります。</div>
<p>デバッガはデバッグ対象とJavaScriptスタックを共有しますが、 <code>Debugger.Frame</code> によってデバッガに提供されているスタックフレームは、デバッガ固有のコードが動作するフレームを含む事はありません。</p>
<div class="note">
  <strong>Note:</strong> ジェネレータ- iterator(繰り返し処理に使います。以前の処理結果を保持し次の計算に渡します)オブジェクトを操作している状態に対応したスタックフレームは、特別な種類の <code>Debugger.Frame</code>を使う事に相当します。</div>
<h3 id="Generator_frames">ジェネレータフレーム</h3>
<p>SpiderMonkeyはジェネレータ-iteratorオブジェクトをサポートしています。関数や命令の実行時に繰り返す事で中断する変数群を提供します。例えば、 <a href="/en/JavaScript/Reference/Operators/yield" title="yield"><code>yield()</code></a> オペレータを用いた関数呼びだしは、ジェネレータ- iterator オブジェクトを提供します。そして、 <code>(各 i の値に対して  i * i (ここで i [1, 2, 3 ]))</code>のような命令を実行して数値を求めます。</p>
<p>ジェネレータ - iterator オブジェクトは、固定の継続したフレームなしにスタックフレームを参照します。ジェネレータのコードが動作している間、その繰り返し処理では、 <code>next()</code> メソッド(ジェネレータが次の結果を要求する)を呼び出すフレームは対象になります。ジェネレータが中断している間は、特別の継続処理用のフレームはありません。そして、それが再開したとき、再開のための継続処理フレームは以前の再開処理時のフレームとは異なっています。</p>
<h4 id="Differences_between_generator_frames_and_other_frames">ジェネレータフレームと他のフレームとの相違</h4>
<p>ジェネレータフレームに相当する <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame" title="Debugger"><code>Debugger.Frame</code></a> のインスタンスは、通常のスタックフレームとは以下の点で異なっています:</p>
<ul>
  <li><code>generator</code> の属性が真</li>
  <li><code>older</code> 属性は、 ジェネレータが動作している間はフレームの継続処理フレームを参照し、ジェネレータが中断している間は <code>null</code> を参照します。</li>
  <li><code>depth</code> 属性は、処理が再開したときはスタック内のフレームの位置を反映し、ジェネレータ中断中は <code>null</code> を表します。</li>
  <li><code>live</code> 属性は、フレームが戻るか、例外を投げるか、強制終了するまで真のままの状態を維持します。それは、スタックの上に存在しない間でもジェネレータのフレームは有効であることを意味しています。</li>
  <li>ジェネレータフレームは、ジェネレータが値を分離し、処理が中断する各段階で消えてなくなります。ジェネレータが次の値を生み出すために再開するときに、スタックの最上位に再び現れます。同じ <code>Debugger.Frame</code> インスタンスは、それが戻るか、例外を投げるか、終了するまでジェネレータフレームを参照します。</li>
</ul>
<div class="note">
  <strong>Note:</strong> ジェネレータが再開するとき、スタック上にある <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame" title="Debugger"><code>Debugger.Frame</code></a> オブジェクトは、新しいオブジェクトか、特定されていないすでにあるオブジェクトかに関わりません。この点で固有の動作に関して信頼すべきではありません。</div>
<h4 id="How_generator_frames_and_other_frames_are_the_same">如何にジェネレータフレームと他のフレームが同じになるか</h4>
<p>すべての他の <code>Debugger.Frame</code> メソッドと属性にアクセスするものは、ジェネレータフレームが中断する時であっても、他の種類のフレームで動作します。あなたは、例えば、そのとき中断させた <a href="/en/JavaScript/Reference/Operators/yield" title="yield"><code>yield()</code></a>オペレーションを監視するために <code>script</code> と <code>offset</code> 属性を使って、ジェネレータフレームの属性を検査することができます。</p>
<h4 id="The_lifespan_of_a_generator_frame">ジェネレータフレームの生存期間</h4>
<p><a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame" title="Debugger"><code>Debugger.Frame</code></a> インスタンスがジェネレータ - iteratorフレームを参照するために、ジェネレータ- iteratorオブジェクトへのしっかりした参照を保持してます。フレームとそのオブジェクトは、<code>Debugger.Frame</code> インスタンスと同じ長さの有効期間を持っています。 しかし、一旦、ジェネレータ関数が戻るか、例外を投げるか、終了すると、 <code>Debugger.Frame</code> のインスタンスは非アクティブになり、 <code>live</code> 属性は偽となり、その他の種別のフレームはポップされます。</p>
<p>一旦ジェネレータフレームが無効になると、ジェネレータ - iteratorオブジェクトへのしっかりした参照はもはや保持されません。</p>
<h3 id="Exception_handling">例外処理</h3>
<h4 id="Exception_unwinding">例外をほどく</h4>
<p>例外が投げられた後、(例外発生時の処理状態等の情報を積み上げた)スタックをほどく必要があります。これは、ハンドラーがその例外を見つけて、スタックからフレームを取り除く処理になります。各フレームがほどく処理の間に至まで、SpiderMonkeyはフレーム内の現在のオフセットが 、投げられた例外を処理するための例外ハンドラーがあることを示している <a href="/en/JavaScript/Reference/Statements/try...catch" title="try...catch"><code>try</code></a> ブロックの中にあれば、そのオフセットを注視します。もしそうであれば、操作はその例外に一致している <code>catch</code>/<code>finally</code> コードへジャンプします。さもなくば、フレームは破棄され、スタックをほどく処理を続けます。</p>
<p>デバッガAPI はデバッガに、フレームをほどく処理の間、各デバッガのスクリプトフレームのために、 <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onExceptionUnwind()" title="en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onExceptionUnwind()"><code>Debugger.onExceptionUnwind()</code></a> メソッドを呼び出すことによって、例外処理の間中スタックをほどく処理をモニターさせます。メソッドはいかに処理の実行が進行するのかを示す、 <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Resumption_values" title="en/SpiderMonkey/JS_Debugger_API_Reference/Resumption_values">再開するための値(resumption value)</a> を戻します。</p>
<h2 id="Scripts">スクリプト</h2>
<p>各 JSAPI <a href="/en/JSScript" title="en/JSScript"><code>JSScript</code></a> オブジェクトは <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Script" title="Debugger.Object"><code>Debugger.Script</code></a> インスタンスに対応しています。そのインスタンスはデバッグ対象内のバイトコードの処理手続きを参照します。それは、以下のような種別の <a href="/en/JSScript" title="en/JSScript"><code>JSScript</code></a> オブジェクトからコードを表します:</p>
<ul>
  <li>関数のボディ、これは関数内のすべてのコードですが、ネストされた関数内のコードは含みません。</li>
  <li>コードは単一の <a href="/en/JavaScript/Reference/Global_Objects/Object/eval" title="eval"><code>eval()</code></a>呼び出しに渡されます。そのコードによって定義される関数のボディはふくみません。</li>
  <li>{{ HTMLElement("script") }} 要素の内容</li>
  <li>HTMLに組み込まれているか、他のJavaScriptコードによって要素に添付されているDOMのイベントハンドラ。</li>
  <li>URL内に <code>javascript:</code> として表示されるコード。</li>
</ul>
<h4 id="How_Debugger.Scripts_are_created">どのようにDebugger.Scriptsは生成されるか</h4>
<p><a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger" title="Debugger"><code>Debugger</code></a> インターフェイスは、存在するスクリプトオブジェクトを見つけるように、 <code>Debugger.Script</code> オブジェクトを生成します。デバッガコードは、スクリプトオブジェクトに所有する属性を追加することができます。これが起こるにはいくつかの方法があります。例えば:</p>
<ul>
  <li>取りかかり口であるオブジェクトメソッド <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onNewScript()" title="en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onNewScript()"><code>Debugger.onNewScript()</code></a> を呼び出す事。</li>
  <li><code>Debugger.Frame.script</code> 属性値の変更。</li>
  <li><code>Debugger.Object.functionScript()</code> メソッドを呼び出す事。</li>
  <li>スクリプトを変更するかもしれないその他の機構。</li>
</ul>
<p>The <code>Debugger</code> インターフェイスは、正確に個別の原スクリプトオブジェクトの <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Script" title="Debugger.Object"><code>Debugger.Script</code></a> インスタンスを生成します。デバッガコードは、後で見つけて参照できるように、所有する属性をスクリプトオブジェクトに追加することができます。単純に二つの記号表示が同じスクリプトを参照しているかどうかを決めるのに <code>==</code> オペレータを使う事ができます。</p>
<p>A <code>Debugger.Script</code> インスタンスは、 <a href="/en/JSScript" title="en/JSScript"><code>JSScript</code></a> オブジェクトへのしっかりとした参照を保持しています。それによって、ガーベージコレクション処理により回収されることからスクリプトを保護します。しかし、 <a href="/en/JavaScript/Reference/Global_Objects/Object/eval" title="eval"><code>eval()</code></a> に渡されるコードに相当するスクリプトは、 <code>eval()</code> が戻ったときに削除されます。そのため、あなたはスクリプトがデバッグ対象として存在しているかどうかを判断するために <code>live</code> 属性の値を検査すべきです。</p>
<div class="note">
  <strong>Note:</strong> SpiderMonkeyは、同じ <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Script" title="Debugger.Object"><code>Debugger.Script</code></a> インスタンスを複数の関数、あるいは、同じ構文解析環境で実行される同じソースファイル内の同じ位置にある同じソースコードに対応したコードセグメントを計算します。</div>
<h2 id="Objects">オブジェクト</h2>
<p>A <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> インスタンスはデバッグしているスクリプト内のオブジェクトに対応しています。デバッガコードはデバッグ対象となるオブジェクトへは直接アクセスしません。代わりに <code>Debugger.Object</code> インスタンスによってデバッグ対象となるオブジェクトを操作し、変更し、参照します。</p>
<p>各 <code>Debugger.Object</code> インスタンスは反応指向(reflection-oriented)なメソッドを持っています。それは参照しているオブジェクト変更、検査させます。あなたは、参照している属性にアクセスするために、 <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#getOwnPropertyDescriptor()" title="https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#getOwnPropertyDescriptor()"><code>Debugger.Object.getOwnPropertyDescriptor()</code></a> と <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#defineProperty()" title="https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#defineProperty()"><code>Debugger.Object.defineProperty()</code></a> のようなメソッドを使うことができます。これはデバッガが、そのデバッグ対象の属性を見るときに、不注意にデバッグ対象内のgetter や setter を呼び出すこのとないよう確認します。</p>
<p>SpiderMonkeyは正確に デバッグ対象内の各オブジェクトのに対する一つの <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> インスタンスを生成します。もし、デバッガが複数の経路を経て(二つの関数が同じオブジェクトを呼び出すときのような)、同じオブジェクトに出くわす場合、毎回、同じ <code>Debugger.Object</code> のインスタンスが存在します。 これはデバッグ対象内で二つの <code>Debugger.Object</code> インスタンスが同じオブジェクトを参照しているときに、それを認識する為に == のようなオペレータを使う事ができることを意味しています。そして、デバッグ対象のオブジェクトに関するあなた固有のメタデータを保存する為に、あなた固有の属性を<code>Debugger.Object</code> インスタンスに追加することができます。</p>
<p>多くの <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> インスタンスは、 デバッグ対象の動作と状態をデバッガに明らかにする間、SpiderMOnkeyによって生成されます。デバッガそれ自身は、デバッグ対象のコンパートメント内にオブジェクトを生成するために、 <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#copy()" title="https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#copy()"><code>Debugger.Object.copy()</code></a> や <a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#create()" title="https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object#create()"><code>Debugger.Object.create()</code></a> を使います。</p>
<p><a href="/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Object" title="Debugger.Object"><code>Debugger.Object</code></a> インスタンスは、ガーベージコレクションから回収対象として参照されることからオブジェクトを保護します。 <code>Debugger.Object</code> インスタンスが有効である限り、それが参照するものも同様に有効なもとして残ります。このように、ガーベージコレクションは、<code>Debugger.Object</code> のインスタンスに対してデバッガから見える影響はありません。</p>
<h2 id="How_values_are_passed_between_debugger_and_debuggee">如何に値はデバッガとデバッグ対象の間で渡されるか</h2>
<p>デバッガが安全にオブジェクトと値をデバッグ対象のコンパートメント内で検査、変更することを支援するために、 <code>Debugger</code> インターフェイスは以下の慣例に従います。:</p>
<ul>
  <li>基本的な値は、デバッガとデバッグ対象の間で自由に渡されます。それらの値でコピーとラッピングが必要となるものは、透過的に取り扱われます。</li>
  <li>デバッグ対象から受け取るオブジェクトは、DOM要素のようなホストオブジェクトを保持します。それは、 <code>Debugger.Object</code> のインスタンスとしてデバッガに含まれています。それらの参照を検査するために反応指向(reflection-oriented) メソッドを提供します。</li>
  <li>デバッガオブジェクトが所有する <code>Debugger.Object</code> インスタンスだけがデバッグ対象に渡す事ができます。これが起きるとき、デバッガは<code>Debugger.Object</code>それ自身ではなく、 <code>Debugger.Object</code> の参照を受け取ります。</li>
</ul>
<h2 id="See_also">以下も参照して下さい</h2>
<ul>
  <li><a href="/en/SpiderMonkey/JS_Debugger_API_Reference" title="en/SpiderMonkey/JS_Debugger_API_Reference">JS Debugger API Reference</a></li>
</ul>
Revert to this revision