mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 00:55:37 +00:00
7e20285e70
The -*- file variable lines -*- establish per-file settings that Emacs will pick up. This patch makes the following changes to those lines (and touches nothing else): - Never set the buffer's mode. Years ago, Emacs did not have a good JavaScript mode, so it made sense to use Java or C++ mode in .js files. However, Emacs has had js-mode for years now; it's perfectly serviceable, and is available and enabled by default in all major Emacs packagings. Selecting a mode in the -*- file variable line -*- is almost always the wrong thing to do anyway. It overrides Emacs's default choice, which is (now) reasonable; and even worse, it overrides settings the user might have made in their '.emacs' file for that file extension. It's only useful when there's something specific about that particular file that makes a particular mode appropriate. - Correctly propagate settings that establish the correct indentation level for this file: c-basic-offset and js2-basic-offset should be js-indent-level. Whatever value they're given should be preserved; different parts of our tree use different indentation styles. - We don't use tabs in Mozilla JS code. Always set indent-tabs-mode: nil. Remove tab-width: settings, at least in files that don't contain tab characters. - Remove js2-mode settings that belong in the user's .emacs file, like js2-skip-preprocessor-directives.
353 lines
10 KiB
JavaScript
353 lines
10 KiB
JavaScript
// -*- 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/. */
|
|
|
|
let ConsolePanelView = {
|
|
_list: null,
|
|
_inited: false,
|
|
_evalTextbox: null,
|
|
_evalFrame: null,
|
|
_evalCode: "",
|
|
_bundle: null,
|
|
_showChromeErrors: -1,
|
|
_enabledPref: "devtools.errorconsole.enabled",
|
|
|
|
get enabled() {
|
|
return Services.prefs.getBoolPref(this._enabledPref);
|
|
},
|
|
|
|
get follow() {
|
|
return document.getElementById("console-follow-checkbox").checked;
|
|
},
|
|
|
|
init: function cv_init() {
|
|
if (this._list)
|
|
return;
|
|
|
|
this._list = document.getElementById("console-box");
|
|
this._evalTextbox = document.getElementById("console-eval-textbox");
|
|
this._bundle = Strings.browser;
|
|
|
|
this._count = 0;
|
|
this.limit = 250;
|
|
this.fieldMaxLength = 140;
|
|
|
|
try {
|
|
// update users using the legacy pref
|
|
if (Services.prefs.getBoolPref("browser.console.showInPanel")) {
|
|
Services.prefs.setBoolPref(this._enabledPref, true);
|
|
Services.prefs.clearUserPref("browser.console.showInPanel");
|
|
}
|
|
} catch(ex) {
|
|
// likely don't have an old pref
|
|
}
|
|
Services.prefs.addObserver(this._enabledPref, this, false);
|
|
},
|
|
|
|
show: function show() {
|
|
if (this._inited)
|
|
return;
|
|
this._inited = true;
|
|
|
|
this.init(); // In case the panel is selected before init has been called.
|
|
|
|
Services.console.registerListener(this);
|
|
|
|
this.appendInitialItems();
|
|
|
|
// Delay creation of the iframe for startup performance
|
|
this._evalFrame = document.createElement("iframe");
|
|
this._evalFrame.id = "console-evaluator";
|
|
this._evalFrame.collapsed = true;
|
|
document.getElementById("console-container").appendChild(this._evalFrame);
|
|
|
|
this._evalFrame.addEventListener("load", this.loadOrDisplayResult.bind(this), true);
|
|
},
|
|
|
|
uninit: function cv_uninit() {
|
|
if (this._inited)
|
|
Services.console.unregisterListener(this);
|
|
|
|
Services.prefs.removeObserver(this._enabledPref, this, false);
|
|
},
|
|
|
|
observe: function(aSubject, aTopic, aData) {
|
|
if (aTopic == "nsPref:changed") {
|
|
// We may choose to create a new menu in v2
|
|
}
|
|
else
|
|
this.appendItem(aSubject);
|
|
},
|
|
|
|
showChromeErrors: function() {
|
|
if (this._showChromeErrors != -1)
|
|
return this._showChromeErrors;
|
|
|
|
try {
|
|
let pref = Services.prefs;
|
|
return this._showChromeErrors = pref.getBoolPref("javascript.options.showInConsole");
|
|
}
|
|
catch(ex) {
|
|
return this._showChromeErrors = false;
|
|
}
|
|
},
|
|
|
|
appendItem: function cv_appendItem(aObject) {
|
|
let index = -1;
|
|
try {
|
|
// Try to QI it to a script error to get more info
|
|
let scriptError = aObject.QueryInterface(Ci.nsIScriptError);
|
|
|
|
// filter chrome urls
|
|
if (!this.showChromeErrors && scriptError.sourceName.substr(0, 9) == "chrome://")
|
|
return;
|
|
index = this.appendError(scriptError);
|
|
}
|
|
catch (ex) {
|
|
try {
|
|
// Try to QI it to a console message
|
|
let msg = aObject.QueryInterface(Ci.nsIConsoleMessage);
|
|
|
|
if (msg.message)
|
|
index = this.appendMessage(msg.message);
|
|
else // observed a null/"clear" message
|
|
this.clearConsole();
|
|
}
|
|
catch (ex2) {
|
|
// Give up and append the object itself as a string
|
|
index = this.appendMessage(aObject);
|
|
}
|
|
}
|
|
if (this.follow) {
|
|
this._list.ensureIndexIsVisible(index);
|
|
}
|
|
},
|
|
|
|
truncateIfNecessary: function (aString) {
|
|
if (!aString || aString.length <= this.fieldMaxLength) {
|
|
return aString;
|
|
}
|
|
let truncatedString = aString.substring(0, this.fieldMaxLength);
|
|
let Ci = Components.interfaces;
|
|
let ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
|
|
Ci.nsIPrefLocalizedString).data;
|
|
truncatedString = truncatedString + ellipsis;
|
|
return truncatedString;
|
|
},
|
|
|
|
appendError: function cv_appendError(aObject) {
|
|
let row = this.createConsoleRow();
|
|
let nsIScriptError = Ci.nsIScriptError;
|
|
|
|
// Is this error actually just a non-fatal warning?
|
|
let warning = aObject.flags & nsIScriptError.warningFlag != 0;
|
|
|
|
let typetext = warning ? "typeWarning" : "typeError";
|
|
row.setAttribute("typetext", this._bundle.GetStringFromName(typetext));
|
|
row.setAttribute("type", warning ? "warning" : "error");
|
|
row.setAttribute("msg", aObject.errorMessage);
|
|
row.setAttribute("category", aObject.category);
|
|
if (aObject.lineNumber || aObject.sourceName) {
|
|
row.setAttribute("href", aObject.sourceName);
|
|
row.setAttribute("line", aObject.lineNumber);
|
|
}
|
|
else {
|
|
row.setAttribute("hideSource", "true");
|
|
}
|
|
// hide code by default, otherwise initial item display will
|
|
// hang the browser.
|
|
row.setAttribute("hideCode", "true");
|
|
row.setAttribute("hideCaret", "true");
|
|
|
|
if (aObject.sourceLine) {
|
|
row.setAttribute("code", this.truncateIfNecessary(aObject.sourceLine.replace(/\s/g, " ")));
|
|
if (aObject.columnNumber) {
|
|
row.setAttribute("col", aObject.columnNumber);
|
|
}
|
|
}
|
|
|
|
let mode = document.getElementById("console-filter").value;
|
|
if (mode != "all" && mode != row.getAttribute("type")) {
|
|
row.collapsed = true;
|
|
}
|
|
|
|
row.setAttribute("onclick", "ConsolePanelView.onRowClick(this)");
|
|
this.appendConsoleRow(row);
|
|
return this._list.getIndexOfItem(row);
|
|
},
|
|
|
|
appendMessage: function cv_appendMessage (aMessage) {
|
|
let row = this.createConsoleRow();
|
|
row.setAttribute("type", "message");
|
|
row.setAttribute("msg", aMessage);
|
|
|
|
let mode = document.getElementById("console-filter").value;
|
|
if (mode != "all" && mode != "message")
|
|
row.collapsed = true;
|
|
|
|
this.appendConsoleRow(row);
|
|
return this._list.getIndexOfItem(row);
|
|
},
|
|
|
|
createConsoleRow: function cv_createConsoleRow() {
|
|
let row = document.createElement("richlistitem");
|
|
row.setAttribute("class", "console-row");
|
|
return row;
|
|
},
|
|
|
|
appendConsoleRow: function cv_appendConsoleRow(aRow) {
|
|
this._list.appendChild(aRow);
|
|
if (++this._count > this.limit) {
|
|
this.deleteFirst();
|
|
}
|
|
},
|
|
|
|
deleteFirst: function cv_deleteFirst() {
|
|
let node = this._list.firstChild;
|
|
this._list.removeChild(node);
|
|
--this._count;
|
|
},
|
|
|
|
appendInitialItems: function cv_appendInitialItems() {
|
|
this._list.collapsed = true;
|
|
let messages = Services.console.getMessageArray();
|
|
|
|
// In case getMessageArray returns 0-length array as null
|
|
if (!messages)
|
|
messages = [];
|
|
|
|
let 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]);
|
|
}
|
|
this._list.collapsed = false;
|
|
},
|
|
|
|
clearConsole: function cv_clearConsole() {
|
|
if (this._count == 0) // already clear
|
|
return;
|
|
this._count = 0;
|
|
|
|
let newRows = this._list.cloneNode(false);
|
|
this._list.parentNode.replaceChild(newRows, this._list);
|
|
this._list = newRows;
|
|
this.selectedItem = null;
|
|
},
|
|
|
|
copyAll: function () {
|
|
let mode = document.getElementById("console-filter").value;
|
|
let rows = this._list.childNodes;
|
|
let copyText = "";
|
|
for (let i=0; i < rows.length; i++) {
|
|
let row = rows[i];
|
|
if (mode == "all" || row.getAttribute ("type") == mode) {
|
|
let text = "* " + row.getAttribute("msg");
|
|
if (row.hasAttribute("href")) {
|
|
text += "\r\n " + row.getAttribute("href") + " line:" + row.getAttribute("line");
|
|
}
|
|
if (row.hasAttribute("code")) {
|
|
text += "\r\n " + row.getAttribute("code") + " col:" + row.getAttribute("col");
|
|
}
|
|
copyText += text + "\r\n";
|
|
}
|
|
}
|
|
let clip = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
|
|
clip.copyString(copyText, document);
|
|
},
|
|
|
|
changeMode: function cv_changeMode() {
|
|
let mode = document.getElementById("console-filter").value;
|
|
if (this._list.getAttribute("mode") != mode) {
|
|
let rows = this._list.childNodes;
|
|
for (let i=0; i < rows.length; i++) {
|
|
let row = rows[i];
|
|
if (mode == "all" || row.getAttribute ("type") == mode)
|
|
row.collapsed = false;
|
|
else
|
|
row.collapsed = true;
|
|
}
|
|
this._list.mode = mode;
|
|
this._list.scrollToIndex(0);
|
|
}
|
|
},
|
|
|
|
onContextMenu: function cv_onContextMenu(aEvent) {
|
|
let row = aEvent.target;
|
|
let text = ["msg", "href", "line", "code", "col"].map(function(attr) row.getAttribute(attr))
|
|
.filter(function(x) x).join("\r\n");
|
|
|
|
ContextMenuUI.showContextMenu({
|
|
target: row,
|
|
json: {
|
|
types: ["copy"],
|
|
string: text,
|
|
xPos: aEvent.clientX,
|
|
yPos: aEvent.clientY
|
|
}
|
|
});
|
|
},
|
|
|
|
onRowClick: function (aRow) {
|
|
if (aRow.hasAttribute("code")) {
|
|
aRow.setAttribute("hideCode", "false");
|
|
}
|
|
if (aRow.hasAttribute("col")) {
|
|
aRow.setAttribute("hideCaret", "false");
|
|
}
|
|
},
|
|
|
|
onEvalKeyPress: function cv_onEvalKeyPress(aEvent) {
|
|
if (aEvent.keyCode == 13)
|
|
this.evaluateTypein();
|
|
},
|
|
|
|
onConsoleBoxKeyPress: function cv_onConsoleBoxKeyPress(aEvent) {
|
|
if ((aEvent.charCode == 99 || aEvent.charCode == 67) && aEvent.ctrlKey && this._list && this._list.selectedItem) {
|
|
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
|
|
clipboard.copyString(this._list.selectedItem.getAttribute("msg"), document);
|
|
}
|
|
},
|
|
|
|
evaluateTypein: function cv_evaluateTypein() {
|
|
this._evalCode = this._evalTextbox.value;
|
|
this.loadOrDisplayResult();
|
|
},
|
|
|
|
loadOrDisplayResult: function cv_loadOrDisplayResult() {
|
|
if (this._evalCode) {
|
|
this._evalFrame.contentWindow.location = "javascript: " + this._evalCode.replace(/%/g, "%25");
|
|
this._evalCode = "";
|
|
return;
|
|
}
|
|
|
|
let resultRange = this._evalFrame.contentDocument.createRange();
|
|
resultRange.selectNode(this._evalFrame.contentDocument.documentElement);
|
|
let result = resultRange.toString();
|
|
if (result)
|
|
Services.console.logStringMessage(result);
|
|
// or could use appendMessage which doesn't persist
|
|
},
|
|
|
|
repeatChar: function cv_repeatChar(aChar, aCol) {
|
|
if (--aCol <= 0)
|
|
return "";
|
|
|
|
for (let i = 2; i < aCol; i += i)
|
|
aChar += aChar;
|
|
|
|
return aChar + aChar.slice(0, aCol - aChar.length);
|
|
}
|
|
};
|