mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 07:17:30 +09:00
Issue N/A - Restore the Toolkit Error Console - Part 1: Toolkit
This commit is contained in:
parent
fe8028fa2e
commit
b5846d500d
27 changed files with 1522 additions and 0 deletions
74
toolkit/components/console/content/console.css
Normal file
74
toolkit/components/console/content/console.css
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
.console-box {
|
||||
-moz-binding: url("chrome://global/content/consoleBindings.xml#console-box");
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.console-rows {
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.console-row[type="error"],
|
||||
.console-row[type="warning"] {
|
||||
-moz-binding: url("chrome://global/content/consoleBindings.xml#error");
|
||||
}
|
||||
|
||||
.console-row[type="message"] {
|
||||
-moz-binding: url("chrome://global/content/consoleBindings.xml#message");
|
||||
}
|
||||
|
||||
.console-msg-text,
|
||||
.console-error-msg {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.console-error-source {
|
||||
-moz-binding: url("chrome://global/content/consoleBindings.xml#console-error-source");
|
||||
}
|
||||
|
||||
.console-dots {
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
/* :::::::::: hiding and showing of rows for each mode :::::::::: */
|
||||
|
||||
.console-box[mode="Warnings"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="error"],
|
||||
.console-box[mode="Messages"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="error"]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.console-box[mode="Errors"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="warning"],
|
||||
.console-box[mode="Messages"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="warning"]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.console-box[mode="Errors"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="message"],
|
||||
.console-box[mode="Warnings"] > .console-box-internal > .console-rows
|
||||
> .console-row[type="message"]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.filtered-by-string {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* If line number is 0, hide the line number section */
|
||||
.lineNumberRow[line="0"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#TextboxEval {
|
||||
direction: ltr;
|
||||
}
|
||||
111
toolkit/components/console/content/console.js
Normal file
111
toolkit/components/console/content/console.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gConsole, gConsoleBundle, gTextBoxEval, gEvaluator, gCodeToEvaluate;
|
||||
var gFilter;
|
||||
|
||||
/* :::::::: Console Initialization ::::::::::::::: */
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
gConsole = document.getElementById("ConsoleBox");
|
||||
gConsoleBundle = document.getElementById("ConsoleBundle");
|
||||
gTextBoxEval = document.getElementById("TextboxEval");
|
||||
gEvaluator = document.getElementById("Evaluator");
|
||||
gFilter = document.getElementById("Filter");
|
||||
|
||||
updateSortCommand(gConsole.sortOrder);
|
||||
updateModeCommand(gConsole.mode);
|
||||
|
||||
gEvaluator.addEventListener("load", loadOrDisplayResult, true);
|
||||
}
|
||||
|
||||
/* :::::::: Console UI Functions ::::::::::::::: */
|
||||
|
||||
function changeFilter()
|
||||
{
|
||||
gConsole.filter = gFilter.value;
|
||||
|
||||
document.persist("ConsoleBox", "filter");
|
||||
}
|
||||
|
||||
function changeMode(aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case "Errors":
|
||||
case "Warnings":
|
||||
case "Messages":
|
||||
gConsole.mode = aMode;
|
||||
break;
|
||||
case "All":
|
||||
gConsole.mode = null;
|
||||
}
|
||||
|
||||
document.persist("ConsoleBox", "mode");
|
||||
}
|
||||
|
||||
function clearConsole()
|
||||
{
|
||||
gConsole.clear();
|
||||
}
|
||||
|
||||
function changeSortOrder(aOrder)
|
||||
{
|
||||
updateSortCommand(gConsole.sortOrder = aOrder);
|
||||
}
|
||||
|
||||
function updateSortCommand(aOrder)
|
||||
{
|
||||
var orderString = aOrder == 'reverse' ? "Descend" : "Ascend";
|
||||
var bc = document.getElementById("Console:sort"+orderString);
|
||||
bc.setAttribute("checked", true);
|
||||
|
||||
orderString = aOrder == 'reverse' ? "Ascend" : "Descend";
|
||||
bc = document.getElementById("Console:sort"+orderString);
|
||||
bc.setAttribute("checked", false);
|
||||
}
|
||||
|
||||
function updateModeCommand(aMode)
|
||||
{
|
||||
/* aMode can end up invalid if it set by an extension that replaces */
|
||||
/* mode and then it is uninstalled or disabled */
|
||||
var bc = document.getElementById("Console:mode" + aMode) ||
|
||||
document.getElementById("Console:modeAll");
|
||||
bc.setAttribute("checked", true);
|
||||
}
|
||||
|
||||
function onEvalKeyPress(aEvent)
|
||||
{
|
||||
if (aEvent.keyCode == 13)
|
||||
evaluateTypein();
|
||||
}
|
||||
|
||||
function evaluateTypein()
|
||||
{
|
||||
gCodeToEvaluate = gTextBoxEval.value;
|
||||
// reset the iframe first; the code will be evaluated in loadOrDisplayResult
|
||||
// below, once about:blank has completed loading (see bug 385092)
|
||||
gEvaluator.contentWindow.location = "about:blank";
|
||||
}
|
||||
|
||||
function loadOrDisplayResult()
|
||||
{
|
||||
if (gCodeToEvaluate) {
|
||||
gEvaluator.contentWindow.location = "javascript: " +
|
||||
gCodeToEvaluate.replace(/%/g, "%25");
|
||||
gCodeToEvaluate = "";
|
||||
return;
|
||||
}
|
||||
|
||||
var resultRange = gEvaluator.contentDocument.createRange();
|
||||
resultRange.selectNode(gEvaluator.contentDocument.documentElement);
|
||||
var result = resultRange.toString();
|
||||
if (result)
|
||||
Services.console.logStringMessage(result);
|
||||
// or could use appendMessage which doesn't persist
|
||||
}
|
||||
101
toolkit/components/console/content/console.xul
Normal file
101
toolkit/components/console/content/console.xul
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0"?> <!-- -*- tab-width: 4; indent-tabs-mode: nil -*- -->
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/console/console.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/content/console.css" type="text/css"?>
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % console SYSTEM "chrome://global/locale/console.dtd"> %console;
|
||||
]>
|
||||
|
||||
<window id="JSConsoleWindow"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&errorConsole.title;"
|
||||
windowtype="global:console"
|
||||
width="640" height="480"
|
||||
screenX="10" screenY="10"
|
||||
persist="screenX screenY width height sizemode"
|
||||
onclose="return closeWindow(false);">
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/console.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/>
|
||||
|
||||
<stringbundle id="ConsoleBundle" src="chrome://global/locale/console.properties"/>
|
||||
|
||||
<commandset id="editMenuCommands"/>
|
||||
|
||||
<commandset id="consoleCommands">
|
||||
<command id="cmd_close" oncommand="closeWindow(true)"/>
|
||||
</commandset>
|
||||
|
||||
<keyset id="consoleKeys">
|
||||
<key id="key_close" key="&closeCmd.commandkey;" modifiers="accel"
|
||||
command="cmd_close"/>
|
||||
<key id="key_close2" keycode="VK_ESCAPE" command="cmd_close"/>
|
||||
<key id="key_focus1" key="&focus1.commandkey;" modifiers="accel"
|
||||
oncommand="gTextBoxEval.focus()"/>
|
||||
<key id="key_focus2" key="&focus2.commandkey;" modifiers="alt"
|
||||
oncommand="gTextBoxEval.focus()"/>
|
||||
</keyset>
|
||||
|
||||
<popupset id="ContextMenus">
|
||||
<menupopup id="ConsoleContext">
|
||||
<menuitem type="radio" id="Console:sortAscend"
|
||||
label="&sortFirst.label;" accesskey="&sortFirst.accesskey;"
|
||||
oncommand="changeSortOrder('forward');"/>
|
||||
<menuitem type="radio" id="Console:sortDescend"
|
||||
label="&sortLast.label;" accesskey="&sortLast.accesskey;"
|
||||
oncommand="changeSortOrder('reverse');"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_copy_cm" command="cmd_copy"
|
||||
label="©Cmd.label;" accesskey="©Cmd.accesskey;"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
<toolbox id="console-toolbox">
|
||||
<toolbar class="chromeclass-toolbar" id="ToolbarMode">
|
||||
<hbox id="viewGroup">
|
||||
<toolbarbutton type="radio" group="mode" id="Console:modeAll"
|
||||
label="&all.label;" accesskey="&all.accesskey;"
|
||||
oncommand="changeMode('All');"/>
|
||||
<toolbarbutton type="radio" group="mode" id="Console:modeErrors"
|
||||
label="&errors.label;" accesskey="&errors.accesskey;"
|
||||
oncommand="changeMode('Errors');"/>
|
||||
<toolbarbutton type="radio" group="mode" id="Console:modeWarnings"
|
||||
label="&warnings.label;" accesskey="&warnings.accesskey;"
|
||||
oncommand="changeMode('Warnings');"/>
|
||||
<toolbarbutton type="radio" group="mode" id="Console:modeMessages"
|
||||
label="&messages.label;" accesskey="&messages.accesskey;"
|
||||
oncommand="changeMode('Messages');"/>
|
||||
</hbox>
|
||||
<toolbarseparator/>
|
||||
<toolbarbutton id="Console:clear" oncommand="clearConsole();"
|
||||
label="&clear.label;" accesskey="&clear.accesskey;"/>
|
||||
</toolbar>
|
||||
|
||||
<toolbar class="chromeclass-toolbar" id="ToolbarEval" align="center" nowindowdrag="true">
|
||||
<label value="&codeEval.label;" accesskey="&codeEval.accesskey;" control="TextboxEval"/>
|
||||
<textbox id="TextboxEval" class="toolbar" value="" onkeypress="onEvalKeyPress(event)" flex="1"/>
|
||||
<toolbarbutton id="ButtonEval" label="&evaluate.label;"
|
||||
accesskey="&evaluate.accesskey;" oncommand="evaluateTypein()"/>
|
||||
</toolbar>
|
||||
</toolbox>
|
||||
|
||||
<vbox id="ConsoleBox" class="console-box" flex="1" context="ConsoleContext" persist="sortOrder"/>
|
||||
|
||||
<iframe name="Evaluator" id="Evaluator" collapsed="true"/>
|
||||
|
||||
<statusbar>
|
||||
<statusbarpanel flex="1" pack="start">
|
||||
<label value="&filter2.label;" control="Filter"/>
|
||||
<textbox accesskey="&filter2.accesskey;" type="search"
|
||||
id="Filter" oncommand="changeFilter();"/>
|
||||
</statusbarpanel>
|
||||
</statusbar>
|
||||
</window>
|
||||
547
toolkit/components/console/content/consoleBindings.xml
Normal file
547
toolkit/components/console/content/consoleBindings.xml
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://global/locale/console.dtd">
|
||||
|
||||
<bindings id="consoleBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="console-box" extends="xul:box">
|
||||
<content>
|
||||
<xul:stringbundle src="chrome://global/locale/console.properties" role="string-bundle"/>
|
||||
<xul:vbox class="console-box-internal">
|
||||
<xul:vbox class="console-rows" role="console-rows" xbl:inherits="dir=sortOrder"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="limit" readonly="true">
|
||||
250
|
||||
</field>
|
||||
|
||||
<field name="fieldMaxLength" readonly="true">
|
||||
<!-- Limit displayed string lengths to avoid performance issues. (Bug 796179 and 831020) -->
|
||||
200
|
||||
</field>
|
||||
|
||||
<field name="showChromeErrors" readonly="true">
|
||||
Services.prefs.getBoolPref("javascript.options.showInConsole");
|
||||
</field>
|
||||
|
||||
<property name="count" readonly="true">
|
||||
<getter>return this.mCount</getter>
|
||||
</property>
|
||||
|
||||
<property name="mode">
|
||||
<getter>return this.mMode;</getter>
|
||||
<setter><![CDATA[
|
||||
if (this.mode != val) {
|
||||
this.mMode = val || "All";
|
||||
this.setAttribute("mode", this.mMode);
|
||||
this.selectedItem = null;
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="filter">
|
||||
<getter>return this.mFilter;</getter>
|
||||
<setter><![CDATA[
|
||||
val = val.toLowerCase();
|
||||
if (this.mFilter != val) {
|
||||
this.mFilter = val;
|
||||
for (let aRow of this.mConsoleRowBox.children) {
|
||||
this.filterElement(aRow);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="sortOrder">
|
||||
<getter>return this.getAttribute("sortOrder");</getter>
|
||||
<setter>this.setAttribute("sortOrder", val); return val;</setter>
|
||||
</property>
|
||||
<field name="mSelectedItem">null</field>
|
||||
<property name="selectedItem">
|
||||
<getter>return this.mSelectedItem</getter>
|
||||
<setter><![CDATA[
|
||||
if (this.mSelectedItem)
|
||||
this.mSelectedItem.removeAttribute("selected");
|
||||
|
||||
this.mSelectedItem = val;
|
||||
if (val)
|
||||
val.setAttribute("selected", "true");
|
||||
|
||||
// Update edit commands
|
||||
window.updateCommands("focus");
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="init">
|
||||
<body><![CDATA[
|
||||
this.mCount = 0;
|
||||
|
||||
this.mConsoleListener = {
|
||||
console: this,
|
||||
observe : function(aObject) {
|
||||
// The message can arrive a little bit after the xbl binding has been
|
||||
// unbind. So node.appendItem will not be available anymore.
|
||||
if ('appendItem' in this.console)
|
||||
this.console.appendItem(aObject);
|
||||
}
|
||||
};
|
||||
|
||||
this.mConsoleRowBox = document.getAnonymousElementByAttribute(this, "role", "console-rows");
|
||||
this.mStrBundle = document.getAnonymousElementByAttribute(this, "role", "string-bundle");
|
||||
|
||||
try {
|
||||
Services.console.registerListener(this.mConsoleListener);
|
||||
} catch (ex) {
|
||||
appendItem(
|
||||
"Unable to display errors - couldn't get Console Service component. " +
|
||||
"(Missing @mozilla.org/consoleservice;1)");
|
||||
return;
|
||||
}
|
||||
|
||||
this.mMode = this.getAttribute("mode") || "All";
|
||||
this.mFilter = "";
|
||||
|
||||
this.appendInitialItems();
|
||||
window.controllers.insertControllerAt(0, this._controller);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="destroy">
|
||||
<body><![CDATA[
|
||||
Services.console.unregisterListener(this.mConsoleListener);
|
||||
window.controllers.removeController(this._controller);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendInitialItems">
|
||||
<body><![CDATA[
|
||||
var messages = Services.console.getMessageArray();
|
||||
|
||||
// In case getMessageArray returns 0-length array as null
|
||||
if (!messages)
|
||||
messages = [];
|
||||
|
||||
var limit = messages.length - this.limit;
|
||||
if (limit < 0) limit = 0;
|
||||
|
||||
// Checks if console ever been cleared
|
||||
for (var i = messages.length - 1; i >= limit; --i)
|
||||
if (!messages[i].message)
|
||||
break;
|
||||
|
||||
// Populate with messages after latest "clear"
|
||||
while (++i < messages.length)
|
||||
this.appendItem(messages[i]);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendItem">
|
||||
<parameter name="aObject"/>
|
||||
<body><![CDATA[
|
||||
try {
|
||||
// Try to QI it to a script error to get more info
|
||||
var scriptError = aObject.QueryInterface(Components.interfaces.nsIScriptError);
|
||||
|
||||
// filter chrome urls
|
||||
if (!this.showChromeErrors && scriptError.sourceName.substr(0, 9) == "chrome://")
|
||||
return;
|
||||
|
||||
// filter private windows
|
||||
if (scriptError.isFromPrivateWindow)
|
||||
return;
|
||||
|
||||
this.appendError(scriptError);
|
||||
} catch (ex) {
|
||||
try {
|
||||
// Try to QI it to a console message
|
||||
var msg = aObject.QueryInterface(Components.interfaces.nsIConsoleMessage);
|
||||
if (msg.message)
|
||||
this.appendMessage(msg.message);
|
||||
else // observed a null/"clear" message
|
||||
this.clearConsole();
|
||||
} catch (ex2) {
|
||||
// Give up and append the object itself as a string
|
||||
this.appendMessage(aObject);
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_truncateIfNecessary">
|
||||
<parameter name="aString"/>
|
||||
<parameter name="aMiddleCharacter"/>
|
||||
<body><![CDATA[
|
||||
if (!aString || aString.length <= this.fieldMaxLength)
|
||||
return {string: aString, column: aMiddleCharacter};
|
||||
let halfLimit = this.fieldMaxLength / 2;
|
||||
if (!aMiddleCharacter || aMiddleCharacter < 0 || aMiddleCharacter > aString.length)
|
||||
aMiddleCharacter = halfLimit;
|
||||
|
||||
let startPosition = 0;
|
||||
let endPosition = aString.length;
|
||||
if (aMiddleCharacter - halfLimit >= 0)
|
||||
startPosition = aMiddleCharacter - halfLimit;
|
||||
if (aMiddleCharacter + halfLimit <= aString.length)
|
||||
endPosition = aMiddleCharacter + halfLimit;
|
||||
if (endPosition - startPosition < this.fieldMaxLength)
|
||||
endPosition += this.fieldMaxLength - (endPosition - startPosition);
|
||||
let truncatedString = aString.substring(startPosition, endPosition);
|
||||
let Ci = Components.interfaces;
|
||||
let ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
if (startPosition > 0) {
|
||||
truncatedString = ellipsis + truncatedString;
|
||||
aMiddleCharacter += ellipsis.length;
|
||||
}
|
||||
if (endPosition < aString.length)
|
||||
truncatedString = truncatedString + ellipsis;
|
||||
|
||||
return {
|
||||
string: truncatedString,
|
||||
column: aMiddleCharacter - startPosition
|
||||
};
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendError">
|
||||
<parameter name="aObject"/>
|
||||
<body><![CDATA[
|
||||
var row = this.createConsoleRow();
|
||||
var nsIScriptError = Components.interfaces.nsIScriptError;
|
||||
|
||||
// Is this error actually just a non-fatal warning?
|
||||
var warning = aObject.flags & nsIScriptError.warningFlag != 0;
|
||||
|
||||
var typetext = warning ? "typeWarning" : "typeError";
|
||||
row.setAttribute("typetext", this.mStrBundle.getString(typetext));
|
||||
row.setAttribute("type", warning ? "warning" : "error");
|
||||
row.setAttribute("msg", aObject.errorMessage);
|
||||
row.setAttribute("category", aObject.category);
|
||||
row.setAttribute("time", this.properFormatTime(aObject.timeStamp));
|
||||
if (aObject.lineNumber || aObject.sourceName) {
|
||||
row.setAttribute("href", this._truncateIfNecessary(aObject.sourceName).string);
|
||||
row.mSourceName = aObject.sourceName;
|
||||
row.setAttribute("line", aObject.lineNumber);
|
||||
} else {
|
||||
row.setAttribute("hideSource", "true");
|
||||
}
|
||||
if (aObject.sourceLine) {
|
||||
let sourceLine = aObject.sourceLine.replace(/\s/g, " ");
|
||||
let truncatedLineObj = this._truncateIfNecessary(sourceLine, aObject.columnNumber);
|
||||
row.setAttribute("code", truncatedLineObj.string);
|
||||
row.mSourceLine = sourceLine;
|
||||
if (aObject.columnNumber) {
|
||||
row.setAttribute("col", aObject.columnNumber);
|
||||
row.setAttribute("errorDots", this.repeatChar(" ", truncatedLineObj.column));
|
||||
row.setAttribute("errorCaret", " ");
|
||||
} else {
|
||||
row.setAttribute("hideCaret", "true");
|
||||
}
|
||||
} else {
|
||||
row.setAttribute("hideCode", "true");
|
||||
}
|
||||
|
||||
this.appendConsoleRow(row);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendMessage">
|
||||
<parameter name="aMessage"/>
|
||||
<parameter name="aType"/>
|
||||
<body><![CDATA[
|
||||
var row = this.createConsoleRow();
|
||||
row.setAttribute("type", aType || "message");
|
||||
row.setAttribute("msg", aMessage);
|
||||
this.appendConsoleRow(row);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="clear">
|
||||
<body><![CDATA[
|
||||
// add a "clear" message (mainly for other listeners)
|
||||
Services.console.logStringMessage(null);
|
||||
Services.console.reset();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="properFormatTime">
|
||||
<parameter name="aTime"/>
|
||||
<body><![CDATA[
|
||||
const dateServ = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
|
||||
.getService(Components.interfaces.nsIScriptableDateFormat);
|
||||
let errorTime = new Date(aTime);
|
||||
return dateServ.FormatDateTime("", dateServ.dateFormatShort, dateServ.timeFormatSeconds,
|
||||
errorTime.getFullYear(), errorTime.getMonth() + 1, errorTime.getDate(),
|
||||
errorTime.getHours(), errorTime.getMinutes(), errorTime.getSeconds());
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="copySelectedItem">
|
||||
<body><![CDATA[
|
||||
if (this.mSelectedItem) try {
|
||||
const clipURI = "@mozilla.org/widget/clipboardhelper;1";
|
||||
const clipI = Components.interfaces.nsIClipboardHelper;
|
||||
var clipboard = Components.classes[clipURI].getService(clipI);
|
||||
|
||||
clipboard.copyString(this.mSelectedItem.toString(), document);
|
||||
} catch (ex) {
|
||||
// Unable to copy anything, die quietly
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="createConsoleRow">
|
||||
<body><![CDATA[
|
||||
var row = document.createElement("box");
|
||||
row.setAttribute("class", "console-row");
|
||||
row._IsConsoleRow = true;
|
||||
row._ConsoleBox = this;
|
||||
return row;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendConsoleRow">
|
||||
<parameter name="aRow"/>
|
||||
<body><![CDATA[
|
||||
this.filterElement(aRow);
|
||||
this.mConsoleRowBox.appendChild(aRow);
|
||||
if (++this.mCount > this.limit) this.deleteFirst();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="deleteFirst">
|
||||
<body><![CDATA[
|
||||
var node = this.mConsoleRowBox.firstChild;
|
||||
this.mConsoleRowBox.removeChild(node);
|
||||
--this.mCount;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="clearConsole">
|
||||
<body><![CDATA[
|
||||
if (this.mCount == 0) // already clear
|
||||
return;
|
||||
this.mCount = 0;
|
||||
|
||||
var newRows = this.mConsoleRowBox.cloneNode(false);
|
||||
this.mConsoleRowBox.parentNode.replaceChild(newRows, this.mConsoleRowBox);
|
||||
this.mConsoleRowBox = newRows;
|
||||
this.selectedItem = null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="filterElement">
|
||||
<parameter name="aRow" />
|
||||
<body><![CDATA[
|
||||
let anyMatch = ["msg", "line", "code"].some(function (key) {
|
||||
return (aRow.hasAttribute(key) &&
|
||||
this.stringMatchesFilters(aRow.getAttribute(key), this.mFilter));
|
||||
}, this) || (aRow.mSourceName &&
|
||||
this.stringMatchesFilters(aRow.mSourceName, this.mFilter));
|
||||
|
||||
if (anyMatch) {
|
||||
aRow.classList.remove("filtered-by-string")
|
||||
} else {
|
||||
aRow.classList.add("filtered-by-string")
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- UTILITY FUNCTIONS -->
|
||||
|
||||
<method name="repeatChar">
|
||||
<parameter name="aChar"/>
|
||||
<parameter name="aCol"/>
|
||||
<body><![CDATA[
|
||||
if (--aCol <= 0)
|
||||
return "";
|
||||
|
||||
for (var i = 2; i < aCol; i += i)
|
||||
aChar += aChar;
|
||||
|
||||
return aChar + aChar.slice(0, aCol - aChar.length);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="stringMatchesFilters">
|
||||
<parameter name="aString"/>
|
||||
<parameter name="aFilter"/>
|
||||
<body><![CDATA[
|
||||
if (!aString || !aFilter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let searchStr = aString.toLowerCase();
|
||||
let filterStrings = aFilter.split(/\s+/);
|
||||
return !filterStrings.some(function (f) {
|
||||
return searchStr.indexOf(f) == -1;
|
||||
});
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<constructor> this.init(); </constructor>
|
||||
<destructor> this.destroy(); </destructor>
|
||||
|
||||
<!-- Command controller for the copy command -->
|
||||
<field name="_controller"><![CDATA[({
|
||||
_outer: this,
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIController) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
|
||||
supportsCommand: function(aCommand) {
|
||||
return aCommand == "cmd_copy";
|
||||
},
|
||||
|
||||
isCommandEnabled: function(aCommand) {
|
||||
return aCommand == "cmd_copy" && this._outer.selectedItem;
|
||||
},
|
||||
|
||||
doCommand: function(aCommand) {
|
||||
if (aCommand == "cmd_copy")
|
||||
this._outer.copySelectedItem();
|
||||
},
|
||||
|
||||
onEvent: function() { }
|
||||
});]]></field>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="mousedown"><![CDATA[
|
||||
if (event.button == 0 || event.button == 2) {
|
||||
var target = event.originalTarget;
|
||||
|
||||
while (target && !("_IsConsoleRow" in target))
|
||||
target = target.parentNode;
|
||||
|
||||
if (target)
|
||||
this.selectedItem = target;
|
||||
}
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="error" extends="xul:box">
|
||||
<content>
|
||||
<xul:box class="console-row-internal-box" flex="1">
|
||||
<xul:box class="console-row-icon" align="center" xbl:inherits="selected">
|
||||
<xul:image class="console-icon" xbl:inherits="src,type"/>
|
||||
</xul:box>
|
||||
<xul:vbox class="console-row-content" xbl:inherits="selected" flex="1">
|
||||
<xul:box class="console-row-msg" align="start">
|
||||
<xul:label class="label" xbl:inherits="value=typetext"/>
|
||||
<xul:description class="console-error-msg" xbl:inherits="xbl:text=msg" flex="1"/>
|
||||
<xul:label class="label console-time" xbl:inherits="value=time"/>
|
||||
</xul:box>
|
||||
<xul:box class="console-row-file" xbl:inherits="hidden=hideSource">
|
||||
<xul:label class="label" value="&errFile.label;"/>
|
||||
<xul:box class="console-error-source" xbl:inherits="href,line"/>
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:hbox class="lineNumberRow" xbl:inherits="line">
|
||||
<xul:label class="label" value="&errLine.label;"/>
|
||||
<xul:label class="label" xbl:inherits="value=line"/>
|
||||
</xul:hbox>
|
||||
</xul:box>
|
||||
<xul:vbox class="console-row-code" xbl:inherits="selected,hidden=hideCode">
|
||||
<xul:label class="monospace console-code" xbl:inherits="value=code" crop="end"/>
|
||||
<xul:box xbl:inherits="hidden=hideCaret">
|
||||
<xul:label class="monospace console-dots" xbl:inherits="value=errorDots"/>
|
||||
<xul:label class="monospace console-caret" xbl:inherits="value=errorCaret"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:box>
|
||||
</xul:vbox>
|
||||
</xul:vbox>
|
||||
</xul:box>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="mSourceName">null</field>
|
||||
<field name="mSourceLine">null</field>
|
||||
|
||||
<method name="toString">
|
||||
<body><![CDATA[
|
||||
let msg = "";
|
||||
let strBundle = this._ConsoleBox.mStrBundle;
|
||||
|
||||
if (this.hasAttribute("time"))
|
||||
msg += strBundle.getFormattedString("errTime", [this.getAttribute("time")]) + "\n";
|
||||
|
||||
msg += this.getAttribute("typetext") + " " + this.getAttribute("msg");
|
||||
|
||||
if (this.hasAttribute("line") && this.mSourceName) {
|
||||
msg += "\n" + strBundle.getFormattedString("errFile",
|
||||
[this.mSourceName]) + "\n";
|
||||
if (this.hasAttribute("col")) {
|
||||
msg += strBundle.getFormattedString("errLineCol",
|
||||
[this.getAttribute("line"), this.getAttribute("col")]);
|
||||
} else
|
||||
msg += strBundle.getFormattedString("errLine", [this.getAttribute("line")]);
|
||||
}
|
||||
|
||||
if (this.hasAttribute("code"))
|
||||
msg += "\n" + strBundle.getString("errCode") + "\n" + this.mSourceLine;
|
||||
|
||||
return msg;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
</binding>
|
||||
|
||||
<binding id="message" extends="xul:box">
|
||||
<content>
|
||||
<xul:box class="console-internal-box" flex="1">
|
||||
<xul:box class="console-row-icon" align="center">
|
||||
<xul:image class="console-icon" xbl:inherits="src,type"/>
|
||||
</xul:box>
|
||||
<xul:vbox class="console-row-content" xbl:inherits="selected" flex="1">
|
||||
<xul:vbox class="console-row-msg" flex="1">
|
||||
<xul:description class="console-msg-text" xbl:inherits="xbl:text=msg"/>
|
||||
</xul:vbox>
|
||||
</xul:vbox>
|
||||
</xul:box>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="toString">
|
||||
<body><![CDATA[
|
||||
return this.getAttribute("msg");
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="console-error-source" extends="xul:box">
|
||||
<content>
|
||||
<xul:label class="text-link" xbl:inherits="value=href" crop="right"/>
|
||||
</content>
|
||||
|
||||
<handlers>
|
||||
<handler event="click" phase="capturing" button="0" preventdefault="true">
|
||||
<![CDATA[
|
||||
var url = document.getBindingParent(this).mSourceName;
|
||||
url = url.substring(url.lastIndexOf(" ") + 1);
|
||||
var line = getAttribute("line");
|
||||
gViewSourceUtils.viewSource(url, null, null, line);
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
9
toolkit/components/console/jar.mn
Normal file
9
toolkit/components/console/jar.mn
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
toolkit.jar:
|
||||
content/global/console.js (content/console.js)
|
||||
content/global/console.xul (content/console.xul)
|
||||
content/global/console.css (content/console.css)
|
||||
content/global/consoleBindings.xml (content/consoleBindings.xml)
|
||||
40
toolkit/components/console/jsconsole-clhandler.js
Normal file
40
toolkit/components/console/jsconsole-clhandler.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
|
||||
/* vim:sw=4:sr:sta:et:sts: */
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function jsConsoleHandler() {}
|
||||
jsConsoleHandler.prototype = {
|
||||
handle: function clh_handle(cmdLine) {
|
||||
if (!cmdLine.handleFlag("jsconsole", false))
|
||||
return;
|
||||
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
var console = wm.getMostRecentWindow("global:console");
|
||||
if (!console) {
|
||||
var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
wwatch.openWindow(null, "chrome://global/content/console.xul", "_blank",
|
||||
"chrome,dialog=no,all", cmdLine);
|
||||
} else {
|
||||
console.focus(); // the Error console was already open
|
||||
}
|
||||
|
||||
if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO)
|
||||
cmdLine.preventDefault = true;
|
||||
},
|
||||
|
||||
helpInfo : " -jsconsole Open the Error console.\n",
|
||||
|
||||
classID: Components.ID("{2cd0c310-e127-44d0-88fc-4435c9ab4d4b}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([jsConsoleHandler]);
|
||||
3
toolkit/components/console/jsconsole-clhandler.manifest
Normal file
3
toolkit/components/console/jsconsole-clhandler.manifest
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
component {2cd0c310-e127-44d0-88fc-4435c9ab4d4b} jsconsole-clhandler.js
|
||||
contract @mozilla.org/toolkit/console-clh;1 {2cd0c310-e127-44d0-88fc-4435c9ab4d4b}
|
||||
category command-line-handler b-jsconsole @mozilla.org/toolkit/console-clh;1
|
||||
14
toolkit/components/console/moz.build
Normal file
14
toolkit/components/console/moz.build
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'jsconsole-clhandler.js',
|
||||
'jsconsole-clhandler.manifest',
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
3
toolkit/components/console/tests/chrome.ini
Normal file
3
toolkit/components/console/tests/chrome.ini
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[DEFAULT]
|
||||
|
||||
[test_hugeURIs.xul]
|
||||
64
toolkit/components/console/tests/test_hugeURIs.xul
Normal file
64
toolkit/components/console/tests/test_hugeURIs.xul
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=796179
|
||||
-->
|
||||
<window title="Mozilla Bug 796179"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="RunTest();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- Detect severe performance and memory issues when large amounts of errors
|
||||
are reported from CSS embedded in a file with a long data URI. Addressed
|
||||
by 786108 for issues internal to the style system and by 796179 for issues
|
||||
related to the error console. This error console test should finish quickly
|
||||
with those patches and run for a very long time or OOM otherwise. -->
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=796179"
|
||||
target="_blank">Mozilla Bug 796179</a>
|
||||
<div id="badSVG" style="max-width: 1; max-height: 1; overflow: hidden"></div>
|
||||
</body>
|
||||
|
||||
<!-- display the error console so we can test its reaction to the test -->
|
||||
<iframe id="errorConsoleFrame" height="400" src="chrome://global/content/console.xul"></iframe>
|
||||
|
||||
<!-- test code -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function RunTest()
|
||||
{
|
||||
// Create the bad SVG and add it to the document.
|
||||
var img = new Array;
|
||||
img.push('<img src="data:image/svg+xml,');
|
||||
img.push(encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="300px">'));
|
||||
|
||||
for (var i = 0 ; i < 10000 ; i++)
|
||||
img.push(encodeURIComponent('<circle cx="0" cy="0" r="1" style="xxx-invalid-property: 0;"/>'));
|
||||
|
||||
img.push(encodeURIComponent('</svg>'));
|
||||
img.push('" />');
|
||||
|
||||
document.getElementById('badSVG').innerHTML = img.join('');
|
||||
|
||||
// We yield control of the thread, allowing the error console to render.
|
||||
// If we get control back without timing out or OOMing then the test passed.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.executeSoon(function() {
|
||||
// Clean up.
|
||||
var elem = document.getElementById('errorConsoleFrame');
|
||||
elem.parentNode.removeChild(elem);
|
||||
elem = document.getElementById('badSVG');
|
||||
elem.parentNode.removeChild(elem);
|
||||
elem = null;
|
||||
|
||||
// Finish the test with a pass.
|
||||
ok(true, 'Error console rendered OK.');
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
|
|
@ -18,6 +18,7 @@ DIRS += [
|
|||
'apppicker',
|
||||
'asyncshutdown',
|
||||
'commandlines',
|
||||
'console',
|
||||
'contentprefs',
|
||||
'contextualidentity',
|
||||
'cookie',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue