このドキュメントでは、Webコンソールブラウザコンソールの出力を拡張およびカスタマイズする方法について説明します。ここでは、コンソールやオブジェクトインスペクタで生成するオブジェクトプレビューを拡張する方法についても学ぶことができます。

このドキュメントは主に Firefox 開発ツールを拡張するアドオン開発者を対象としています。

出力のスタイリング

コンソール出力にロードされるメインスタイルシートは webconsole.css です。テーマのこのファイルにスタイルを追加したいと思うでしょう。ブラウザツールボックスまたは DOM インスペクタアドオンを使用して、コンソール出力マークアップの構造、使用される要素およびクラスを検索します。

あなたの拡張機能では webconsole.xul にスタイルとカスタム動作を追加できます。

Firefox のテーマについてさらに調べる

メッセージの追加

Web コンソールにメッセージを追加するには、まず使用する API とメッセージがどのタブに属しているかを判断する必要があります。以下に説明するように、いくつかのオプションがあります。

nsIConsoleService を使用する

nsIScriptError インスタンスを作成し、メッセージの innerWindowID を、メッセージを表示するタブの最上位ウィンドウの内部ウィンドウ ID と同じに設定します。タブ内の iframe の内側のウィンドウ ID を使用することもできます。

nsiConsoleService から到着するメッセージは、CSS、Security または JavaScript カテゴリのいずれかに入れられます。スクリプトエラーの正しいカテゴリと重大度を設定していることを確認してください。

スクリプトエラーに内部ウィンドウ ID がない場合、または ID が間違っている場合は、必要なタブの Web コンソールにメッセージが表示されません。これらのメッセージはすべてブラウザコンソールに表示されます (Firefox 24 で紹介されています)。

nsIScriptError を使用するサンプルコード:

const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const WARN_FLAG = Ci.nsIScriptError.warningFlag;
const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG;

Cu.import("resource://gre/modules/Services.jsm");

// Log a message to the Web Console using an nsIScriptError.
function logMessage({flags, message, category, url,
                     lineText, line, column, windowId}) {
  let scriptError = Cc["@mozilla.org/scripterror;1"]
                    .createInstance(Ci.nsIScriptError);
  if (windowId) {
    scriptError.initWithWindowID(message, url, lineText, line,
                                 column, flags, category, windowId);
  } else {
    scriptError.init(message, url, lineText, line, column, flags, category);
  }
  Services.console.logMessage(scriptError);
}

// Get the innerWindowID of the given window.
function getInnerWindowID(win) {
  try {
     let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIDOMWindowUtils);
     return utils.currentInnerWindowID;
  } catch (ex) {  }

  return null;
}

// Log a "hello world" message for a given window |win|.
logMessage({
  flags: WARN_FLAG,
  message: "hello world",
  url: "http://example.com/script.js",
  line: 10,
  windowId: getInnerWindowID(win),
});

また Cu.reportError() を使用してスクリプトのエラーを記録することもできます。このメソッドは特に例外に便利です。

文字列をブラウザコンソールに記録するにはnsIConsoleService.logStringMessage() を使用できます。

コンソール API を使用する

ウィンドウオブジェクトの場合、console API を使用して Web コンソールにメッセージを追加できます。これらのメッセージは「ページロギング」カテゴリにのみ関連付けられているため、可能な限り避けてください。スクリプトから来ていないメッセージが表示されると、ユーザーは混乱します。

Chrome ウィンドウのメッセージはブラウザコンソールに表示されます。これはアドオンに便利です。

JavaScript モジュールでは以下を行うことができます:

const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
console.log("hello world", foo);

その後コンソール API 呼び出しが端末に表示されます (文字列のみ。dump() が有効な場合)。すぐに Console.jsm をインポートする必要はありません。バグ 965860 のすべてのパッチが来てからです。

Web コンソールアウトプット API を使用する

Gecko 29.0 が必要(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)

まず、必要なタブの Web Console オブジェクトインスタンスを取得する必要があります。このためには、DevTools API を使用する必要があります。

const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});

function getWebConsole(tab) {
  // |tab| is the XUL tab for the page you want.
  let target = devtools.TargetFactory.forTab(tab);
  let toolbox = gDevTools.getToolbox(target);
  let panel = toolbox ? toolbox.getPanel("webconsole") : null;
  return panel ? panel.hud : null;
}

WebConsole オブジェクトを取得したら、次のようなメッセージを追加できます。

// Get the Messages object which holds the main classes of Messages
// used by the Web Console.
const {Messages} = devtools.require("devtools/webconsole/console-output");

// Create the simplest message we can.
let msg = new Messages.Simple("hello world", {
  category: "js",
  severity: "error",
});

// Add it to the output.
let hud = getWebConsole(myTab);
hud.ui.output.addMessage(msg);

HUD (Heads-Up Display) は、Web コンソールを参照するために使用した古い用語です。私たちは便宜上それを使い続けています。

ブラウザコンソールへのメッセージの出力

Web コンソール API を使用してブラウザコンソールにメッセージを出力するには、次の操作を行います。

// Get HUDService - the Web/Browser Consoles manager.
const hudservice = devtools.require("devtools/webconsole/hudservice");

// Get the Browser Console - there can only be one.
// This method returns null if the Browser Console is not open.
let browserConsole = hudservice.getBrowserConsole();

// Add a message.
browserConsole.ui.output.addMessage(msgObject);

Messages API

Gecko 29.0 が必要(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)

次の表に使用できるメッセージクラスの一覧を示します。新しいメッセージを作成するには、次の操作を行います。

let msg = new Messages.ConstructorName();
Message クラスの一覧
コンストラクタ 詳細
BaseMessage() BaseMessage オブジェクトはすべてのタイプのメッセージに使用されます。すべての種類のメッセージは、このオブジェクトをベースとして使用する必要があります。このクラスによって提供される機能はありません。
NavigationMarker(url, time)

NavigationMarker は、ページロードイベントを表示するために使用されます。引数:

url (string):
表示する URL
time (number):
メッセージのタイムスタンプ(Unix エポックからのミリ秒)。
Simple(msg[, options]) Simple メッセージは、Web コンソールの基本メッセージを表示するために使用されます。コンストラクタ引数の詳細を参照してください。
Extended(msg[, options]) このクラスは、複数のリンクインライン、オブジェクト、カスタムフラグメントレンダリングを持つメッセージを表示するためのサポートを追加します。コンストラクタ引数の詳細を参照してください。
JavaScriptEvalOutput(evalResponse[, errorMessage])

これは Web コンソールによって JS 評価結果を表示するために使用されます。引数:

evalResponse (object):
サーバから受信した JS 評価レスポンスパケット
errorMessage (optional, string):
評価エラーメッセージ。
ConsoleGeneric(packet) リモートデバッグプロトコルを通じてサーバーから受信した consoleAPICall パケットで説明されているように、console API メソッド呼び出しを表示します。このメッセージクラスはlog()info()warn()error()exception()debug()count() および assert() メソッドでのみ使用されます。
ConsoleTrace(packet) console.trace() メソッド呼び出しを表示します。

このセクションでは、あらゆる種類のメッセージ、メソッド、およびプロパティの包括的なリストの提供はありません。console-output.js を必ずチェックしてください。

Messages.BaseMessage

BaseMessage オブジェクトはすべてのタイプのメッセージに使用されます。すべての種類のメッセージは、このオブジェクトをベースとして使用する必要があります。このクラスによって提供される機能はありません。

BaseMessage メソッドとプロパティ
メソッド/プロパティ 説明
object output ConsoleOutput オブジェクトのインスタンス
HTMLElement element メッセージの DOM 要素。これはメッセージがレンダリングされた後にのみ使用できます。
document document メッセージが存在する DOM ドキュメント。
string textContent テキストのみのメッセージ表現。
object init(output[, parent])

メッセージの初期化方法。引数:

output (object):
メッセージを所有する ConsoleOutput インスタンス
parent (optional, object):
親メッセージ。現在使用されていません。

戻り値: メッセージインスタンス自体

string getRepeatID() 重複したメッセージを追跡するために使用されるこのメッセージオブジェクトの一意でない ID。異なるメッセージの種類は、独自の基準に基づいて識別できます。
object render()

メッセージをレンダリングします。このメソッドが呼び出されると、message.element プロパティはこのメッセージの DOM 要素をポイントします。

戻り値: メッセージインスタンス自体

void _addLinkCallback(element[, callback]) 指定した DOM 要素にクリックコールバックを追加します。コールバックが指定されていない場合は、新しいタブでアンカーリンクを開くために一般的なアンカークリックハンドラが使用されます。コールバックは単一の左クリックに対してのみ呼び出され、追加のクリックイベントでは呼び出されません (右/中/二重のクリックに対する呼び出しなし)。デフォルトのイベントハンドラは、コールバックが呼び出される前に防止されます。
void destroy() メッセージが削除されると呼び出されます。

Messages.Simple

Simple メッセージは、Web コンソールの基本メッセージを表示するために使用されます。このクラスは BaseMessage を拡張します。コンストラクタ引数:

message (string|element|function):
表示するメッセージ DOM 要素が与えられた場合、その要素はメッセージ本文に挿入されます。関数が与えられた場合、その関数は1つの引数、すなわちメッセージオブジェクトを伴って呼び出され、その結果は DOM要素 であると想定され、その後メッセージ本文に挿入されます。
options (optional, object):
このメッセージのオプション:
category (string):
このメッセージが属するカテゴリ。デフォルトはカテゴリなしです。
severity (string):
メッセージの重大度。デフォルトは重大度なしです。
timestamp (number):
メッセージが記録された日時。デフォルトは Date.now() です。
link (string):
提供されている場合、メッセージはここで指定された URL を指すアンカーにラップされます。
linkCallback (function):
提供されている場合、メッセージはアンカーでラップされます。linkCallback 関数が click イベントハンドラとして追加されます。
location (object):
urllinecolumn、および lineText のメッセージソースを示します。
className (string):
スタイリングの目的で追加する要素クラス名。
private (boolean):
これをプライベートメッセージとしてマークしてください。
filterDuplicates (boolean):
このメッセージを潜在的な重複メッセージとしてフィルタリングする場合は true、そうでない場合は false

次の表では Messages.Simple API の一部について説明します。

Messages.Simple のメソッドとプロパティ
メソッド/プロパティ 説明
string category メッセージカテゴリ。
string severity メッセージの重大度。
object|null location メッセージの場所:urllinecolumn、および lineText
number timestamp Unix エポックからの時間 (ミリ秒)。
boolean private このメッセージがプライベートウィンドウ/タブに記録されているかどうかを伝えます。
element _renderBody() メッセージ本体 DOM 要素をレンダリングします。
element _renderRepeatNode() リピート数を表示するために使用される DOM 要素をレンダリングします。
element _renderLocation() メッセージソースの場所の DOM 要素をレンダリングします。

Simple メッセージクラスは、メッセージ出力の最も一般的なニーズをカバーする必要があります。拡張機能は _render*() メソッドをオーバーライドして、任意の基準 (カテゴリ、重大度、場所など) に基づいて、これらのタイプのメッセージのスタイリングまたは動作を変更できます。

例:

const {Messages} = devtools.require("devtools/webconsole/console-output");

// Add a link.
let msg = new Messages.Simple("this is a link", {
  link: "http://example.com/page",
});
hud.output.addMessage(msg);

// Add a link with a callback function.
msg = new Messages.Simple("click me", {
  linkCallback: function() {
    msg.element.style.background = "red";
  },
});
hud.output.addMessage(msg);

あなたは hudMessages オブジェクトが驚くべきものだと思いますか? Web コンソールアウトプット API の使用方法を学びます。

Messages.Extended

Extended メッセージクラスは、Web コンソールが複数の要素がインラインであるオブジェクトアクターまたはメッセージを表示する必要がある場合に使用されます。このクラスは、Simple クラスを継承します。コンストラクタ引数:

messagePieces (array):
表示するメッセージを要素の配列として渡します。各配列要素は、DOM 要素、関数、ObjectActorLongString または文字列です。
options (optional, object):
Messages.Simple と同じオプションに加えて、次のものが指定可能です
quoteStrings (boolean):
文字列を引用符で囲むかどうかを指定します。
Messages.Extended メソッドとプロパティ
メソッド/プロパティ 説明
element _renderBodyPieceSeparator() メッセージの間にセパレータをレンダリングします。
element _renderBodyPiece(piece) messagePieces 配列から要素を描画します。
element _renderValueGrip(grip[, options])

サーバーから受け取った値を表すグリップをレンダリングします。このメソッドは、適切なウィジェットを選択して値をレンダリングします。グリップは文字列やブール値などのプリミティブな値を表すことができますが、オブジェクトを表すこともできます。その場合、グリップは ObjectActor グリップです。

引数:

grip:
サーバーから受け取った値グリップ。
options (optional, object):
値を表示するオプション:
noStringQuotes (boolean):
レンダラーは文字列の周りに引用符を使用しないように指示します。
concise (boolean):
グリップをコンパクトに表示するようにレンダラーに指示します。これは通常、オブジェクトを配列プレビューで表示する必要がある場合は true に設定され、オブジェクトプレビューなどではプロパティ値として設定されます。

このメソッドは、次のように呼び出されます。

  • 指定された部分が DOM 要素でも関数でもない場合、_renderBodyPiece()
  • 値のグリップをインラインで表示する必要があるその他のメッセージメソッドまたはウィジェットメソッド。たとえば、配列やオブジェクトのプレビューアは、このメソッドを呼び出して配列要素やオブジェクトのプロパティ値を表示します。
element _renderObjectActor(actor[, options]) 適切なレンダラーでオブジェクトアクターを表示します。このメソッドは _renderValueGrip() と同じオプションをとります。オブジェクトプレビューの仕組みの詳細をご覧ください。

使用例:

const {Messages} = devtools.require("devtools/webconsole/console-output");
const XHTML_NS = "http://www.w3.org/1999/xhtml";

// Create a DOM element to be added in this message.
let file = hud.output.document.createElementNS(XHTML_NS, "a");
file.textContent = "foobar.js";
file.href = "http://example.com/foobar.js";

// Use a function to display an interactive button.
// This is invoked when the message is rendered.
function button(msg) {
  let clicks = 0;
  let elem = msg.document.createElementNS(XHTML_NS, "button");
  elem.textContent = "click me " + Date.now();
  elem.onclick = function() {
    elem.textContent = "clicks " + (++clicks);
  };
  return elem;
}

// Create the message object.
let pieces = ["there was an error in ", file, button];
let msg = new Messages.Extended(pieces, {
  category: "js",
  severity: "error",
});

// Make sure a click on the file name opens the anchor in a new tab.
msg._addLinkCallback(file);

// Add the new message.
hud.output.addMessage(msg);

あなたは hudMessages オブジェクトが驚くべきものだと思いますか? Web コンソールアウトプット API の使用方法を学びます。

新しいタイプのメッセージを追加する

Web コンソールで複雑な種類のメッセージを作成する場合は、再利用可能な Message クラスを作成することができます。既存の Message クラスを拡張するだけです。

const {Messages} = devtools.require("devtools/webconsole/console-output");
const Heritage = require("sdk/core/heritage");

Messages.RandomPrefix = function(msg) {
  this._onClick = this._onClick.bind(this);

  let prefix = this._getPrefix();
  Messages.Simple.call(this, prefix + msg, {
    linkCallback: this._onClick,
  });
};

Messages.RandomPrefix.prototype = Heritage.extend(Messages.Simple.prototype,
{
  _onClick: function() {
    let body = this.element.querySelector(".body");
    let newPrefix = this._getPrefix();
    body.textContent = body.textContent.replace(/^\[[\d.]+\]/, newPrefix);
  },

  _getPrefix: function() {
    return "[" + Math.random() + "] ";
  },
};

// Later you can use this message class.
let msg = new Messages.RandomPrefix("oh la la");
hud.output.addMessage(msg);

カスタムメッセージに必要なのはこれだけです。

オブジェクトのプレビューをカスタマイズする

Web コンソールは、コンテンツページの JavaScript オブジェクトに直接アクセスすることはできません。コンソールは、サーバーからの JS オブジェクトを記述する JSON パケットのみを受け取ります。これらのオブジェクトは、Object Actor によって提供されます。このようなオブジェクトの出力をコンソールクライアントコードでカスタマイズすることができます。また、JSON パケットに必要なものを追加するためにサーバーを拡張することもできます。

このドキュメントでは、次のオブジェクトアクタープロパティについて説明します。

type (string):
オブジェクトの typeof の結果
class (string):
インスタンスが参照するオブジェクトの ECMAScript クラス。文字列として指定します。これは RegExpNumberDateArraySetMapObject から WindowHTMLDocumentHTMLBodyElement などのどれでもかまいません。
displayString (optional, string):
サーバーはオブジェクトを表示するための推奨文字列を含むことができます。
preview (optional, object):
サーバは、付加的なプレゼンテーション情報を有するオブジェクトを含むことができます。たとえば、配列の場合、プレビューオブジェクトには最初の10要素と配列の長さが含まれます。オブジェクトタイプごとに、プレビューオブジェクトが異なる場合があります。
kind (optional, string):
最も一般的なプレビューオブジェクトには、オブジェクトプレビューの種類が予想されることを示す kind プロパティが含まれています。異なるオブジェクトクラスおよびタイプは、同じプレビュー形式を共有することができます。たとえば、配列、型付き配列、セット、DOMTokenList などのオブジェクトクラスは、ArrayLike プレビュー形式を共有します。

about:config で devtools.debugger.log を true に設定して、デバッガサーバーによって送受信された生の JSON パケットを確認する必要があります。

String-only output

Gecko 29.0 が必要(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)

文字列のみの出力は、Web コンソールおよび JS デバッガのオブジェクトインスペクタで使用されます。Web コンソールは、任意のオブジェクトに対してリッチアウトプットレンダラーが使用できない場合にこの方法を使用します。

文字列のみのプレビューは VariablesView.getString() によって生成されます。VariablesView.jsm を参照してください。サーバーから値グリップが与えられた関数である stringifier を追加することができます。

文字列は、次のようにグループ化されます。

VariablesView stringifier カテゴリーのリスト
オブジェクト 説明
VariablesView.stringifiers.byType ここでは必要なオブジェクトタイプにストリングを追加できます。たとえば、VariablesView.stringifiers.byType.string は文字列の表示に使用されます。このオブジェクトでは、longStringobject の文字列を見つけることもできます。
VariablesView.stringifiers.byObjectClass ネイティブオブジェクトクラスのための Stringifier。 例として、Number を表示する関数を次に示します。DateRegExp なども同様です。
VariablesView.stringifiers.byObjectKind オブジェクトプレビューア "種類" のためのStringifier。ここでは、ArrayLikeMapLikeDOMNode などで使用されている文字列を見ることができます。

上の表の各オブジェクトは、型、オブジェクトクラス、またはオブジェクト型から関数へのマップを保持します。この関数は、次の引数で呼び出されます。

valueGrip:
リモートデバッガプロトコルで定義されている値グリップ。
options (object, optional):
文字列表示のオプション:
concise (boolean):
簡潔にフォーマットされた文字列を生成する必要があるかどうかを示します。これは、オブジェクトプレビューが親オブジェクトのプレビューの一部である場合に使用されます。たとえば、配列要素のプレビューが生成されると concisetrue に設定されます。
noStringQuotes (boolean):
文字列を引用しないように指示します。
noEllipsis (boolean):
longString の最初のテキストの後に省略符を追加しないように指示します。
stringifier は VariablesView.getString() と同じ引数をとります。これは getString() 引数の説明です。

戻り値: 各 stringifier は、表示される文字列を返すことが期待されます。stringifier が null を返すと、より一般的な stringifier が使用されます。この戻り値を使用して、指定した値グリップのプレビューを提供できないことを明示的に通知できます。

関数の表示に使用される文字列の例を次に示します。

const {VariablesView} = Cu.import("resource:///modules/devtools/VariablesView.jsm", {});

VariablesView.stringifiers.byObjectClass.Function = function(grip, {concise}) {
  let name = grip.userDisplayName || grip.displayName || grip.name || "";
  name = VariablesView.getString(name, { noStringQuotes: true });

  let params = grip.parameterNames || "";
  if (!concise) {
    return "function " + name + "(" + params + ")";
  }
  return (name || "function ") + "(" + params + ")";
};

Rich output

Gecko 30.0 が必要(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)

Web コンソール Message オブジェクトは、Widgets を使用してオブジェクトアクター、スタックフレーム、およびさまざまなメッセージ間で再利用可能なその他の出力要素を表示します。

Stacktrace ウィジェットを使用する Message クラスの例を次に示します。

// Get the Widgets object - this is where we can find all of the
// console output widgets.
const {Messages, Widgets} = devtools.require("devtools/webconsole/console-output");
const Heritage = require("sdk/core/heritage");

// The stacktrace argument is expected to use the same format as that
// of the console.trace() calls provided over the remote debugging protocol.
Messages.StalkyMuch = function(stacktrace) {
  Messages.BaseMessage.call(this);
  this._stacktrace = stacktrace;
};

Messages.StalkyMuch.prototype = Heritage.extend(Messages.BaseMessage.prototype,
{
  render: function() {
    let stack = new Widgets.Stacktrace(this, this._stacktrace).render();
    let render = Messages.BaseMessage.prototype.render.bind(this);
    render().element.appendChild(stack.element);
    return this;
  },
};

// Later you can do this:
let msg = new Messages.StalkyMuch(stackFromServer);
hud.output.addMessage(msg);

Tip 1: console-output.js の実際の Messages.ConsoleTraceWidgets.Stacktrace の実装を見ることができます。

Tip 2: あなたは hudMessages オブジェクトが驚くべきものだと思いますか? Web Console出力APIを使用する方法を学ぶ

ウィジェット API

以下の表は、使用可能なウィジェットの概要です。

Widget クラスの一覧
コンストラクタ 説明
BaseWidget(message)

これはすべてのウィジェットの基本クラスです。message 引数は、親メッセージのインスタンスである必要があります。

MessageTimestamp(message, timestamp)

各メッセージのタイムスタンプを表示するウィジェット。timestamp 引数は、UNIX エポックからのミリ秒数でなければなりません。

JSObject(message, objectActor[, options])

特定のオブジェクトレンダラーを持たないオブジェクトアクターを表示するために使用されます。これはすべての ObjectRenderer の基本クラスでもあります。

LongString(message, longStringActor) これは、長い文字列を表示するために使用されます。
Stacktrace(message, stacktrace) スタックトレースを表示するために使用します。

BaseWidget API:

BaseWidget メソッドとプロパティ
メソッド/プロパティ 説明
object message 所有メッセージオブジェクト。
element element

ウィジェットの DOM 要素。これは render() が呼び出された後で利用可能です。

document document ウィジェットがレンダリングされる DOM ドキュメント。
object output このウィジェットを所有する ConsoleOutput インスタンス。
object render()

ウィジェットの DOM 要素をレンダリングします。このメソッドは this.element プロパティを使用可能にする必要があります。

戻り値: ウィジェットインスタンス自体

void destroy() ウィジェットのインスタンスを破棄します。メモリリークを避けるために、イベントリスナーを削除します。
element el(tagName[, attributes[, textContent]])
element el(tagName[, textContent])

DOM 要素を作成するヘルパー。
引数:

tagName (string):
新しいDOM要素のタグ名。必要に応じて、最後に #id を追加したり .class.names.you.need を追加することができます。これらは適切なクラス名として追加され、要素 ID も設定されます。
attributes (optional, object):
新しい DOM 要素に設定する属性名と値のマップ。
textContent (optional, string):
要素に追加するテキストコンテンツ。

使用方法:

// Create element "tag" with ID "id"
// and two class names: "class" and "names".
this.el("tag#id.class.names");

// A <span attr1=value1> element
this.el("span", { attr1: "value1"}) 

// A <p attr1=value1>text content<p> element.
this.el("p", { attr1: "value1", ... }, "text content");

// A <p>text content</p> element.
this.el("p", "text content");

例として、console-output.jsMessageTimestamp ウィジェットがあります:

const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {Widgets} = devtools.require("devtools/webconsole/console-output");
const Heritage = require("sdk/core/heritage");
const WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
const l10n = new WebConsoleUtils.l10n(STRINGS_URI);
const XHTML_NS = "http://www.w3.org/1999/xhtml";

Widgets.MessageTimestamp = function(message, timestamp) {
  Widgets.BaseWidget.call(this, message);
  this.timestamp = timestamp;
};

Widgets.MessageTimestamp.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
{
  timestamp: 0,
  render: function() {
    if (this.element) {
      return this;
    }

    this.element = this.document.createElementNS(XHTML_NS, "span");
    this.element.className = "timestamp devtools-monospace";
    this.element.textContent = l10n.timestampString(this.timestamp) + " ";

    return this;
  },
});

オブジェクトレンダラー API

オブジェクトの豊富な出力のためにウィジェットを使用し、それらを Widgets.ObjectRenderers オブジェクトにグループ化します。ほとんどの場合、Widgets.JSObject はこれらすべてのオブジェクトレンダラーの基本クラスですが、これは必須ではありません。便宜上のものです。

ObjectRenderer カテゴリの一覧
オブジェクト 説明
Widgets.ObjectRenderers.byClass

特定のオブジェクトクラスのウィジェット。ここでは、DateFunction などのオブジェクトを表示するために使用されるウィジェットを見つけることができます。

Widgets.ObjectRenderers.byKind

特定のプレビューの種類のウィジェット。ここでは ArrayLikeMapLikeDOMEventDOMNode オブジェクトなどの表示に使用されるウィジェットを見つけることができます。

ObjectRenderers の各ウィジェットコンストラクタは、Messages.Extended_renderObjectActor(objectActor[, options]) メソッドと同じ引数で呼び出されます。

objectActor (object):
サーバーから受け取った ObjectActor グリップ。
options (optional, object):
値を表示するオプション:
noStringQuotes (boolean):
レンダラーは文字列の周りに引用符を使用しないように指示します。
concise (boolean):
グリップをコンパクトに表示するようにレンダラーに指示します。これは通常、オブジェクトを配列プレビューで表示する必要がある場合は true に設定され、オブジェクトプレビューなどではプロパティ値として設定されます。

ObjectRenderer ウィジェットには canRender(objectActor) という静的メソッドを含めることもできます。これはウィジェットが構築される前に利用可能である場合に呼び出されます。このメソッドには ObjectActor グリップのみが与えられます。true が返された場合はウィジェットを使用してオブジェクトを表示し、そうでない場合はより汎用的なレンダラーが使用されます。

 

オブジェクトレンダラーを追加する

 

オブジェクトレンダラーを追加するヘルパー関数があります。これは Widgets.ObjectRenders.add(descriptor) です。
プロパティ:

byClass (optional, string):
このレンダラーは指定されたオブジェクトクラスに使用されます。
byKind (optional, string):
このレンダラーは指定されたオブジェクトの種類に使用されます。byClass または byKind プロパティの1つを指定する必要があります。
extends (optional, object):
レンダラーオブジェクトは指定されたオブジェクトを拡張します。デフォルト:Widgets.JSObject
boolean canRender(objectActor) (optional, function):
このメソッドは候補オブジェクトを表示する必要があるときに呼び出されます。この関数は静的メソッドとして呼び出されるため、レンダラーオブジェクトのプロパティは使用できません。1つの引数が関数に渡されますが、これはオブジェクトアクターグリップをサーバーから受け取ります。このメソッドが true を返す場合、このレンダラーはオブジェクトの表示に使用されます。
void initialize(ownerMessage, objectActor[, options]) (optional, function):
レンダラーウィジェットのコンストラクタ。この関数は、次の引数で呼び出されます。
  • 所有者メッセージオブジェクトインスタンス、
  • オブジェクトアクタがグリップして表示する
  • オプションオブジェクト。このオブジェクトの詳細については、前のセクションを参照してください。
void render() (required, function):
指定されたオブジェクトアクターを表示するメソッド。前のセクションで説明したように、このメソッドは this.element プロパティを使用できるようにする必要があります。

記述子の他のメソッドやプロパティは、Widgets.ObjectRenderers に追加された新しい Widget オブジェクトのプロトタイプに設定されます。

例として、Date に使用されるオブジェクトレンダラーを次に示します。

const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {Widgets} = devtools.require("devtools/webconsole/console-output");

Widgets.ObjectRenderers.add({
  byClass: "Date",

  render: function() {
    let {preview} = this.objectActor;
    this.element = this.el("span.class-" + this.objectActor.class);

    let anchorText = this.objectActor.class;
    let anchorClass = "cm-variable";
    if ("timestamp" in preview && typeof preview.timestamp != "number") {
      anchorText = new Date(preview.timestamp).toString(); // invalid date
      anchorClass = "";
    }

    this._anchor(anchorText, { className: anchorClass });

    if (!("timestamp" in preview) || typeof preview.timestamp != "number") {
      return;
    }

    this._text(" ");

    let elem = this.el("span.cm-string-2", new Date(preview.timestamp).toISOString());
    this.element.appendChild(elem);
  },
});

Add object previewers to the server

Gecko 29.0 が必要(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)

デバッガサーバーは、Object Actor グリップをクライアントに送信します。JSON パケットは、script.js で生成されます。オブジェクトアクターに詳細を追加するには、DebuggerServer.ObjectActorPreviewers オブジェクトに関数を追加する必要があります。このオブジェクトは、ネイティブオブジェクトのクラス名を関数の配列にマップします (Debugger.Objectclass プロパティを参照)。

デバッガサーバーがクラス k を持つオブジェクトアクターを要求されると、DebuggerServer.ObjectActorPreviewers[k] の各関数を実行します。この関数が true を返すと、オブジェクトプレビューアの検索が停止します。いずれの関数も true を返さない場合、探索はジェネリックな "Object" クラス、DebuggerServer.ObjectActorPreviewers.Object 配列で再び開始されます。ここでは、オブジェクトクラスとは異なる基準に基づいてプレビューの詳細を追加する関数を追加できます。

あなたの関数は、以下の引数で呼び出されます:

objectActor (object):
オブジェクトのプレビューが必要な ObjectActor インスタンス
grip (object):
アクターグリップは、リモートデバッグプロトコルを介してクライアントに送信されるオブジェクトです。
rawObject (optional, object):
これは、コンテンツスクリプトの変更のない、コンテンツページからの生の JavaScript オブジェクトです。たとえば、DOM 要素を指定すると、コンテンツスクリプトによって追加されたプロパティは見つかりません。この引数は、変更されていない JS オブジェクトを常に提供できるわけではないため、オプションです。

プレビューア機能は grip オブジェクトを変更して、クライアントに必要な追加のプロパティを追加する必要があります。コンベンションでは、grip.preview オブジェクトを使用して適切と思われるものを追加します。これらのプレビューアは頻繁に呼び出されることに注意してください。注意を払い、パフォーマンスに注意してください。

注意すべきこと:

  • objectActor 引数には、使用する JS オブジェクトをラップする Debugger.Object である obj プロパティが格納されます
  • 前述の Debugger.Object API を使用して、obj からプロパティを読み込み、および/またはコンテンツページで関数を実行する必要があります
  • rawObj 引数は XPConnect ラッピングの対象です
  • オブジェクトをクライアントに送信する前に、次のことを行う必要があります。(1) Debugger.ObjectmakeDebuggeeValue() メソッドを使用してデバッグ対象の値にします (まだデバッガオブジェクトでない場合)。次に
    (2) ThreadActorcreateValueGrip() メソッドを呼び出します。これは objectActor.threadActor から使用できます
  • 経験則:あなたが扱うオブジェクトに期待されるプロパティがあるとは決して信用できません。そのため、常にそのようなオブジェクトを扱うために Debugger API を使用する必要があります
  • あなたは script.js を見たいと思うでしょう

コードベースの例:

// Import the DebuggerServer.
const {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
const {DevToolsUtils} = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});

// Add the previewer for CSSStyleRules in the generic Object class.
// Use unshift() to add elements in front of other previewers.
DebuggerServer.ObjectActorPreviewers.Object
  .unshift(function CSSStyleRule({obj, threadActor}, aGrip, aRawObj) {
    // Check if this is the type of object we can provide previews for.
    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMCSSStyleRule)) {
      return false;
    }
    aGrip.preview = {
      kind: "ObjectWithText",
      text: threadActor.createValueGrip(aRawObj.selectorText),
    };
    return true;
  },

  // The previewer we use for Errors.
  function Error({obj, threadActor}, aGrip) {
    switch (obj.class) {
      case "Error":
      case "EvalError":
      case "RangeError":
      case "ReferenceError":
      case "SyntaxError":
      case "TypeError":
      case "URIError":
        let name = DevToolsUtils.getProperty(obj, "name");
        let msg = DevToolsUtils.getProperty(obj, "message");
        let stack = DevToolsUtils.getProperty(obj, "stack");
        let fileName = DevToolsUtils.getProperty(obj, "fileName");
        let lineNumber = DevToolsUtils.getProperty(obj, "lineNumber");
        let columnNumber = DevToolsUtils.getProperty(obj, "columnNumber");
        aGrip.preview = {
          kind: "Error",
          name: threadActor.createValueGrip(name),
          message: threadActor.createValueGrip(msg),
          stack: threadActor.createValueGrip(stack),
          fileName: threadActor.createValueGrip(fileName),
          lineNumber: threadActor.createValueGrip(lineNumber),
          columnNumber: threadActor.createValueGrip(columnNumber),
        };
        return true;
      default:
        return false;
    }
  });

これはすべてです! デベロッパーツールを読んでいただきありがとうございます。質問がありますか? デベロッパーツールチームにお問い合わせください

ドキュメントのタグと貢献者

このページの貢献者: silverskyvicto
最終更新者: silverskyvicto,