Our volunteers haven't translated this article into Română yet. Join us and help get the job done!
This document describes how you can extend and customize the output of the Web Console and of the Browser Console. Here you can also learn how to extend the object previews we generate in the consoles and in the Object Inspector.
This document is mainly intended for add-on developers who want to extend the Firefox developer tools.
Output styling
The main style sheet loaded in the console output is webconsole.css
. You will want to add any styles to this file in your theme. Use the Browser Toolbox or the DOM Inspector addon to find the structure of the console output markup, the elements and classes used.
In your extension you can add styles and custom behavior to the webconsole.xul
.
Learn more about theming Firefox.
Add messages
To add a message to the Web Console you need to first determine which API you want to use and which tab the message belongs to. You have several options, as described below.
Use the nsIConsoleService
Create an nsIScriptError
instance and set the innerWindowID
of the message to be the same as the inner window ID of the top level window of the tab where you want the message to be displayed. You can also use the inner window ID of any iframe contained within the tab.
Any message arriving from the nsiConsoleService
is put into one of the CSS, Security or JavaScript categories. Make sure you set the correct category and severity for the script error.
If the script error does not have any inner window ID, or if the ID is incorrect, the message will not be shown in the Web Console of the tab you want. You should see all of these messages in the Browser Console (introduced in Firefox 24).
Example code which uses 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: "https://example.com/script.js",
line: 10,
windowId: getInnerWindowID(win),
});
You can also use Cu.reportError()
to log script errors. This method is particularly useful with exceptions.
To log a string to the Browser Console you can use nsIConsoleService.logStringMessage()
.
Use the console API
For any window object you can use the console API
to add messages to the Web Console. Do note that these messages are only associated to the "page logging" category and this should be avoided whenever possible. Users will be confused if they see messages that do not come from their scripts.
Chrome windows will have their messages shown in the Browser Console. This is useful for addons.
In JavaScript Modules you can do the following:
const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
console.log("hello world", foo);
Then any console API call will show in your terminal (string-only, if dump()
is enabled) and in the Browser Console. Soon you will not need to import Console.jsm
- once all patches from bug 965860 land.
Use the Web Console output API
Requires Gecko 29.0(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)First you need to get the WebConsole
object instance for the tab you want. For this you need to use the 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;
}
Once you have the WebConsole
object you can add a message like this:
// 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) is the old term we used for referring to the Web Console. We continue to use it for convenience.
Output a message in the Browser Console
If you want to use the Web Console API to output a message to the Browser Console you can do this:
// 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
Requires Gecko 29.0(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)In the following table you see a list of message classes you can use. To create a new message you can do:
let msg = new Messages.ConstructorName();
Constructor | Description |
---|---|
BaseMessage() |
The BaseMessage object is used for all types of messages. Every kind of message should use this object as its base. No functionality is provided by this class. |
NavigationMarker(url, time) |
The
|
Simple(msg[, options]) |
The Simple message is used to show any basic message in the Web Console. See details about the constructor arguments. |
Extended(msg[, options]) |
This class adds support for displaying messages with multiple links inline, objects and custom fragment rendering. See details about the constructor arguments. |
JavaScriptEvalOutput(evalResponse[, errorMessage]) |
This is used by the Web Console to display the JS evaluation results. Arguments:
|
ConsoleGeneric(packet) |
Displays a console API method call as described by a consoleAPICall packet received from the server through the remote debugging protocol. This message class is only used for the log(), info(), warn(), error(), exception(), debug(), count() and assert() methods. |
ConsoleTrace(packet) |
Displays a console.trace() method call. |
In this section we do not attempt to provide an exhaustive list of all kinds of messages, methods and properties. You should always check console-output.js
.
Messages.BaseMessage
The BaseMessage
object is used for all types of messages. Every kind of message should use this object as its base. No functionality is provided by this class.
Method/property | Description |
---|---|
object output |
ConsoleOutput object instance. |
|
The message DOM element. This is available only after the message is rendered. |
|
The DOM document where the message exists. |
string textContent |
The text-only message representation. |
object init(output[, parent]) |
Message initialization method. Arguments:
Return value: the message instance itself. |
string getRepeatID() |
Non-unique ID for this message object used for tracking duplicate messages. Different message kinds can identify themselves based their own criteria. |
object render() |
Render the message. After this method is invoked the Return value: the message instance itself. |
void _addLinkCallback(element[, callback]) |
Add a click callback to the given DOM element. If the callback is not given, a generic anchor click handler is used for opening anchor links in new tabs. Note that the callback is invoked only for single left clicks, not for additional click events (no invocation for right/middle/double clicks). The default event handler is prevented before the callback is invoked. |
void destroy() |
Invoked when the message is removed. |
Messages.Simple
The Simple
message is used to show any basic message in the Web Console. This class extends BaseMessage
. Constructor arguments:
-
message
(string|
):element
|function - the message to display. If a DOM element is given the element will be inserted into the message body. If a function is given, then the function is invoked with one argument, the message object, and the result is expected to be a DOM element which is then inserted into the message body.
-
options
(optional, object): -
options for this message:
-
category
(string): - the category that this message belongs to. Defaults to no category.
-
severity
(string): - severity of the message. Defaults to no severity.
-
timestamp
(number): -
date and time when the message was recorded. Defaults to
Date.now()
. -
link
(string): - if provided, the message will be wrapped in an anchor pointing to the given URL here.
-
linkCallback
(function): -
if provided, the message will be wrapped in an anchor. The
linkCallback
function will be added as click event handler. -
location
(object): -
tells the message source:
url
,line
,column
andlineText
. -
className
(string): - additional element class names for styling purposes.
-
private
(boolean): - mark this as a private message.
-
filterDuplicates
(boolean): -
true
if you want this message to be filtered as a potential duplicate message,false
otherwise.
-
The following table describes a part of the Messages.Simple
API:
Method/property | Description |
---|---|
string category |
Message category. |
string severity |
Message severity. |
object|null location |
Message location: url , line , column and lineText . |
number timestamp |
Time in milliseconds since the Unix epoch. |
boolean private |
Tells if this message was logged in a private window/tab or not. |
|
Render the message body DOM element. |
|
Render the DOM element used to display the number of repeats. |
|
Render the message source location DOM element. |
The Simple
message class should cover most common needs for message output. Extensions can override the _render*()
methods to change the styling or behavior of these types of messages, based on any criteria (category, severity, location, etc).
Examples:
const {Messages} = devtools.require("devtools/webconsole/console-output");
// Add a link.
let msg = new Messages.Simple("this is a link", {
link: "https://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);
Do you find the hud
and Messages
objects surprising? Learn how to use the Web Console output API.
Messages.Extended
The Extended
message class is used whenever the Web Console needs to display object actors or messages with multiple elements inline. This class extends the Simple
class. Constructor arguments:
-
messagePieces
(array): -
the message to display given as an array of elements. Each array element can be a DOM element, function,
ObjectActor
,LongString
or a string. -
options
(optional, object): -
same options as
Messages.Simple
, plus the following:-
quoteStrings
(boolean): - tells if you want strings to be wrapped in quotes or not.
-
Method/property | Description |
---|---|
|
Render the separator between the pieces of the message. |
|
Render an element from messagePiece s array. |
|
Render a grip that represents a value received from the server. This method picks the appropriate widget to render the value with. A grip can represent primitive values like strings and booleans, but it can also represent objects. In that case the grip is an Arguments:
This method is invoked by:
|
|
Display an object actor with the appropriate renderer. This method takes the same options as _renderValueGrip() . Learn more about how object preview works. |
Example use:
const {Messages} = devtools.require("devtools/webconsole/console-output");
const XHTML_NS = "https://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 = "https://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);
Do you find the hud
and Messages
objects surprising? Learn how to use the Web Console output API.
Add new types of messages
If you want to create complex kinds of messages in the Web Console you may want to create a reusable Message
class. Simply extend any of the existing message classes:
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);
That's all you need for custom messages.
Customize previews for objects
The Web Console does not have direct access to the JavaScript objects from the content page. The console only receives a JSON packet that describes the JS object from the server - these are provided by the Object Actor. You can customize the output for such objects in console client code, and you can also extend the server to add anything you need to the JSON packet.
For the purpose of this document we describe here the following object actor properties:
-
type
(string): -
the result of
typeof
for the object. -
class
(string): -
The ECMAScript Class of the object to which the instance refers, as a string. This can be anything from
RegExp, Number, Date, Array, Set, Map, Object
toWindow, HTMLDocument, HTMLBodyElement
, etc. -
displayString
(optional, string): - the server can include a suggested string for displaying the object.
-
preview
(optional, object): -
the server can include an object with additional presentational information. For example, for arrays the preview object includes the first 10 elements and the array length. For each object type the preview object can be different.
-
kind
(optional, string): -
most commonly preview objects include the
kind
property to indicate the kind of object preview is expected. Different object classes and types can share the same preview kind. For example arrays, typed arrays, sets,DOMTokenList
and other object classes share theArrayLike
preview format.
-
You should set devtools.debugger.log to true
in about:config to see the raw JSON packets sent and received by the debugger server.
String-only output
Requires Gecko 29.0(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)String-only output is used by the object inspector in the Web Console and in the JS Debugger. The web console uses this approach when rich output renderers are not available for any given object.
String-only previews are generated by VariablesView.getString()
- see VariablesView.jsm
. You can add stringifiers, functions that are given the value grip from the server.
Stringifiers are grouped as follows:
Object | Description |
---|---|
VariablesView.stringifiers.byType |
Here you can add a stringifier for the object type you want. For example VariablesView.stringifiers.byType.string is used for displaying strings. In this object you can also find stringifiers for longString and object . |
VariablesView.stringifiers.byObjectClass |
Stringifiers for native object classes. For example, here you can find functions for displaying Number . Date , RegExp and more. |
VariablesView.stringifiers.byObjectKind |
Stringifiers for object previewer "kinds". Here you can see the stringifiers used for ArrayLike , MapLike , DOMNode and more. |
Each of the objects in the table above holds a map of types, object classes or object kinds to functions. The function is invoked with the following arguments:
-
valueGrip
: - the value grip as defined in the remote debugger protocol.
-
options
(object, optional): -
Options for string display:
-
concise
(boolean): -
tells if a concisely formatted string should be generated. This is used when the object preview is part of the preview of a parent object. For example,
concise
is set totrue
when previews for array elements are generated. -
noStringQuotes
(boolean): - tells to not quote strings.
-
noEllipsis
(boolean): -
tells to not add an ellipsis after the initial text of a
longString
.
-
The stringifiers take the same arguments as VariablesView.getString()
. This is the description of the getString()
arguments.
Return value: each stringifier is expected to return the string to be displayed. If the stringifier returns null
, then a more generic stringifier is used. You can use this return value to explicitly notify you cannot provide a preview for the given value grip.
Here is an example stringifier used for displaying functions:
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
Requires Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)The Web Console Message
objects use Widgets
to display object actors, stack frames and other well-contained output elements that can be reused between different messages.
Here is an example Message
class that uses the Stacktrace
widget:
// 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: You can see the actual Messages.ConsoleTrace
and Widgets.Stacktrace
implementations in console-output.js
.
Tip 2: Do you find the hud
and Messages
objects surprising? Learn how to use the Web Console output API.
Widgets API
The table below is an overview of the available widgets you can use.
Constructor | Description |
---|---|
BaseWidget(message) |
This is the base class for all widgets. The message argument needs to be the parent message instance. |
MessageTimestamp(message, timestamp) |
Widget used to display the timestamp for each message. The timestamp argument must be the number of milliseconds since the UNIX epoch. |
JSObject(message, objectActor[, options]) |
This is used to display object actors for which we do not have any more specific object renderer. This is also the base class for all of the ObjectRenderers . |
LongString(message, longStringActor) |
This is used to display long strings. |
Stacktrace(message, stacktrace) |
This is used to display stack traces. |
The BaseWidget
API:
Method/property | Description |
---|---|
object message |
The owning message object. |
|
The DOM element of the widget. This is available after render() is invoked. |
|
The DOM document where the widget is rendered. |
object output |
The ConsoleOutput instance that owns this widget. |
object render() |
Renders the widget's DOM element. This method must make the Return value: the widget instance itself. |
void destroy() |
Destroy the widget instance - remove any event listeners to avoid memory leaks. |
|
Helper for creating DOM elements. Arguments:
Usage:
|
As an example, here is the MessageTimestamp
widget from console-output.js
:
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 = "https://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;
},
});
Object renderers API
For rich output of objects we use widgets and we keep them grouped in the Widgets.ObjectRenderers
object. Most often Widgets.JSObject
is the base class of all these object renderers, but that is not a requirement - it's just for convenience.
Object | Description |
---|---|
Widgets.ObjectRenderers.byClass |
Widgets for specific object classes. Here you can find the widgets used to display objects like Date and Function . |
Widgets.ObjectRenderers.byKind |
Widgets for specific preview kinds. Here you can find the widgets used to display ArrayLike, MapLike, DOMEvent, DOMNode objects and more. |
Each widget constructor from ObjectRenderers is invoked with the same arguments as the _renderObjectActor(objectActor[, options])
method from Messages.Extended
:
-
objectActor
(object): -
the
ObjectActor
grip received from the server. -
options
(optional, object): -
options for displaying the value:
-
noStringQuotes
(boolean): - tells the renderer to not use quotes around strings.
-
concise
(boolean): -
tells the renderer to compactly display the grip. This is typically set to
true
when the object needs to be displayed in an array preview, or as a property value in object previews, etc.
-
The ObjectRenderer
widgets can also have a static method named canRender(objectActor)
. This is invoked, if available, before the widget is constructed. This method is given only the ObjectActor
grip. If true
is returned, the widget is used to display the object, otherwise a more generic renderer is used.
Add an object renderer
We have a helper function for adding object renderers, this is Widgets.ObjectRenders.add(descriptor)
. Properties:
-
byClass
(optional, string): - this renderer will be used for the given object class.
-
byKind
(optional, string): -
this renderer will be used for the given object kind. One of the
byClass
orbyKind
properties must be provided. -
extends
(optional, object): -
the renderer object extends the given object. Default:
Widgets.JSObject
. -
boolean canRender(objectActor)
(optional, function): -
this method is invoked when a candidate object needs to be displayed. The function is invoked as a static method, as such, none of the properties of the renderer object will be available. One argument is passed to the function: the object actor grip received from the server. If the method returns
true
, then this renderer is used for displaying the object, otherwise not. -
void initialize(ownerMessage, objectActor[, options])
(optional, function): -
the constructor of the renderer widget. This function is invoked with the following arguments:
- the owner message object instance,
- the object actor grip to display, and
- an options object. Read the previous section for details about this object.
-
void render()
(required, function): -
the method that displays the given object actor. This method must make the
this.element
property available for use, as explained in the previous section.
Any other methods and properties in the descriptor will be set on the prototype of the new Widget object that is added to Widgets.ObjectRenderers
.
As an example here is the object renderer used for 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
Requires Gecko 29.0(Firefox 29.0 / Thunderbird 29.0 / SeaMonkey 2.26)script.js
. To add more details to object actors you need to add your function to the DebuggerServer.ObjectActorPreviewers
object. This object maps native object class names to arrays of functions, see the class
property of Debugger.Object
.
When the debugger server is asked for an object actor with class k it goes through each function of DebuggerServer.ObjectActorPreviewers[k]
. If the function returns true
the search for an object previewer stops. If none of the functions return true
then the search starts again in the generic "Object" class, the DebuggerServer.ObjectActorPreviewers.Object
array. Here you can add functions that add preview details based on different criteria than the object class.
Your function is invoked with the following arguments:
-
objectActor
(object): - the ObjectActor instance for which an object preview is needed.
-
grip
(object): - the actor grip, the object which will be sent to the client through the remote debugging protocol.
-
rawObject
(optional, object): - this is the raw JavaScript object from the content page without any content script changes. For example, given a DOM element you will not find properties added by the content scripts. This argument is optional because we cannot always provide an unmodified JS object.
The previewer function needs to modify the grip
object to add any additional properties needed in the client. The convention is to use a grip.preview
object where you add anything you see fit. Do note that these previewers are invoked often - please exercise care and pay attention to performance.
Things to note:
- the
objectActor
argument holds theobj
property which is aDebugger.Object
which wraps the JS object we work with. - you will need to use the aforementioned
Debugger.Object
API to read properties fromobj
and/or execute functions in the content page. - the
rawObj
argument is subject to XPConnect wrapping. - before you can send an object to the client you need to: (1) make it a Debuggee value, using the
makeDebuggeeValue()
method ofDebugger.Object
(if it is not already a debugger object), then (2) call thecreateValueGrip()
method of theThreadActor
- it is available throughobjectActor.threadActor
. - rule of thumb: never trust that the object you work with has the expected properties. This is why you should always use the Debugger API to work with such objects.
- you will most-likely want to look at
script.js
.
Examples from the codebase:
// 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;
}
});
This is all! Thank you for reading and extending our developer tools! Do you have questions? Contact the developer tools team.