--- a/devtools/client/definitions.js
+++ b/devtools/client/definitions.js
@@ -88,26 +88,26 @@ Tools.inspector = {
isTargetSupported: function (target) {
return target.hasActor("inspector");
},
build: function (iframeWindow, toolbox) {
return new InspectorPanel(iframeWindow, toolbox);
}
};
-
Tools.webConsole = {
id: "webconsole",
key: l10n("cmd.commandkey"),
accesskey: l10n("webConsoleCmd.accesskey"),
modifiers: Services.appinfo.OS == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 2,
+ oldWebConsoleURL: "chrome://devtools/content/webconsole/webconsole.xul",
+ newWebConsoleURL: "chrome://devtools/content/webconsole/webconsole.xhtml",
icon: "chrome://devtools/skin/images/tool-webconsole.svg",
invertIconForDarkTheme: true,
- url: "chrome://devtools/content/webconsole/webconsole.xul",
label: l10n("ToolboxTabWebconsole.label"),
menuLabel: l10n("MenuWebconsole.label"),
panelLabel: l10n("ToolboxWebConsole.panelLabel"),
get tooltip() {
return l10n("ToolboxWebconsole.tooltip2",
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + this.key);
},
inMenu: true,
@@ -121,21 +121,33 @@ Tools.webConsole = {
panel.focusInput();
return undefined;
},
isTargetSupported: function () {
return true;
},
-
build: function (iframeWindow, toolbox) {
return new WebConsolePanel(iframeWindow, toolbox);
}
};
+function switchWebconsole() {
+ if (Services.prefs.getBoolPref("devtools.webconsole.new-frontend-enabled")) {
+ Tools.webConsole.url = Tools.webConsole.newWebConsoleURL;
+ } else {
+ Tools.webConsole.url = Tools.webConsole.oldWebConsoleURL;
+ }
+}
+switchWebconsole();
+
+Services.prefs.addObserver(
+ "devtools.webconsole.new-frontend-enabled",
+ { observe: switchWebconsole }
+);
Tools.jsdebugger = {
id: "jsdebugger",
key: l10n("debuggerMenu.commandkey"),
accesskey: l10n("debuggerMenu.accesskey"),
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 3,
icon: "chrome://devtools/skin/images/tool-debugger.svg",
--- a/devtools/client/framework/toolbox-process-window.js
+++ b/devtools/client/framework/toolbox-process-window.js
@@ -61,18 +61,18 @@ function setPrefDefaults() {
Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
Services.prefs.setBoolPref("browser.dom.window.dump.enabled", true);
Services.prefs.setBoolPref("devtools.command-button-noautohide.enabled", true);
Services.prefs.setBoolPref("devtools.scratchpad.enabled", true);
// Bug 1225160 - Using source maps with browser debugging can lead to a crash
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", false);
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
Services.prefs.setBoolPref("devtools.debugger.client-source-maps-enabled", true);
+ Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
}
-
window.addEventListener("load", function () {
let cmdClose = document.getElementById("toolbox-cmd-close");
cmdClose.addEventListener("command", onCloseCommand);
setPrefDefaults();
connect().catch(e => {
let errorMessageContainer = document.getElementById("error-message-container");
let errorMessage = document.getElementById("error-message");
errorMessage.value = e.message || e;
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -5,16 +5,17 @@
devtools.jar:
% content devtools %content/
content/shared/vendor/d3.js (shared/vendor/d3.js)
content/shared/vendor/dagre-d3.js (shared/vendor/dagre-d3.js)
content/shared/widgets/widgets.css (shared/widgets/widgets.css)
content/netmonitor/src/assets/styles/netmonitor.css (netmonitor/src/assets/styles/netmonitor.css)
content/shared/widgets/VariablesView.xul (shared/widgets/VariablesView.xul)
content/netmonitor/index.html (netmonitor/index.html)
+ content/webconsole/webconsole.xhtml (webconsole/webconsole.xhtml)
content/webconsole/webconsole.xul (webconsole/webconsole.xul)
content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul)
content/scratchpad/scratchpad.js (scratchpad/scratchpad.js)
content/shared/splitview.css (shared/splitview.css)
content/shared/theme-switching.js (shared/theme-switching.js)
content/shared/frame-script-utils.js (shared/frame-script-utils.js)
content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul)
content/storage/storage.xul (storage/storage.xul)
@@ -145,16 +146,17 @@ devtools.jar:
skin/images/command-eyedropper.svg (themes/images/command-eyedropper.svg)
skin/images/command-rulers.svg (themes/images/command-rulers.svg)
skin/images/command-measure.svg (themes/images/command-measure.svg)
skin/images/command-noautohide.svg (themes/images/command-noautohide.svg)
skin/markup.css (themes/markup.css)
skin/images/editor-error.png (themes/images/editor-error.png)
skin/images/breakpoint.svg (themes/images/breakpoint.svg)
skin/webconsole.css (themes/webconsole.css)
+ skin/new-webconsole.css (themes/new-webconsole.css)
skin/images/webconsole.svg (themes/images/webconsole.svg)
skin/images/breadcrumbs-scrollbutton.png (themes/images/breadcrumbs-scrollbutton.png)
skin/images/breadcrumbs-scrollbutton@2x.png (themes/images/breadcrumbs-scrollbutton@2x.png)
skin/animationinspector.css (themes/animationinspector.css)
skin/canvasdebugger.css (themes/canvasdebugger.css)
skin/debugger.css (themes/debugger.css)
skin/performance.css (themes/performance.css)
skin/memory.css (themes/memory.css)
--- a/devtools/client/locales/en-US/webConsole.dtd
+++ b/devtools/client/locales/en-US/webConsole.dtd
@@ -1,26 +1,21 @@
<!-- 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/. -->
-
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
- keep it in English, or another language commonly spoken among web developers.
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
-
<!ENTITY window.title "Web Console">
-<!ENTITY browserConsole.title "Browser Console">
-
<!-- LOCALIZATION NOTE (openURL.label): You can see this string in the Web
- Console context menu. -->
<!ENTITY openURL.label "Open URL in New Tab">
<!ENTITY openURL.accesskey "T">
-
<!-- LOCALIZATION NOTE (btnPageNet.label): This string is used for the menu
- button that allows users to toggle the network logging output.
- This string and the following strings toggle various kinds of output
- filters. -->
<!ENTITY btnPageNet.label "Net">
<!ENTITY btnPageNet.tooltip "Log network access">
<!ENTITY btnPageNet.accesskey "N">
<!-- LOCALIZATION NOTE (btnPageNet.accesskeyMacOSX): This string is used as
--- a/devtools/client/locales/en-US/webconsole.properties
+++ b/devtools/client/locales/en-US/webconsole.properties
@@ -1,26 +1,24 @@
# 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/.
-
# LOCALIZATION NOTE
# The correct localization of this file might be to keep it in
# English, or another language commonly spoken among web developers.
# You want to make that choice consistent across the developer tools.
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
-
-
+# LOCALIZATION NOTE (browserConsole.title): shown as the
+# title when opening the browser console popup
+browserConsole.title=Browser Console
# LOCALIZATION NOTE (timestampFormat): %1$02S = hours (24-hour clock),
# %2$02S = minutes, %3$02S = seconds, %4$03S = milliseconds.
timestampFormat=%02S:%02S:%02S.%03S
-
helperFuncUnsupportedTypeError=Can’t call pprint on this type of object.
-
# LOCALIZATION NOTE (NetworkPanel.deltaDurationMS): this string is used to
# show the duration between two network events (e.g request and response
# header or response header and response body). Parameters: %S is the duration.
NetworkPanel.durationMS=%Sms
ConsoleAPIDisabled=The Web Console logging API (console.log, console.info, console.warn, console.error) has been disabled by a script on this page.
# LOCALIZATION NOTE (webConsoleWindowTitleAndURL): the Web Console floating
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -6,27 +6,25 @@
var WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
const {extend} = require("devtools/shared/extend");
var {TargetFactory} = require("devtools/client/framework/target");
var {Tools} = require("devtools/client/definitions");
const { Task } = require("devtools/shared/task");
var promise = require("promise");
var Services = require("Services");
-
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
loader.lazyRequireGetter(this, "WebConsoleFrame", "devtools/client/webconsole/webconsole", true);
+loader.lazyRequireGetter(this, "NewWebConsoleFrame", "devtools/client/webconsole/new-webconsole", true);
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
loader.lazyRequireGetter(this, "showDoorhanger", "devtools/client/shared/doorhanger", true);
loader.lazyRequireGetter(this, "viewSource", "devtools/client/shared/view-source");
-
const l10n = require("devtools/client/webconsole/webconsole-l10n");
-
const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
// The preference prefix for all of the Browser Console filters.
const BROWSER_CONSOLE_FILTER_PREFS_PREFIX = "devtools.browserconsole.filter.";
var gHudId = 0;
// The HUD service
@@ -196,36 +194,31 @@ HUD_SERVICE.prototype =
});
}
let target;
function getTarget(aConnection)
{
return TargetFactory.forRemoteTab(aConnection);
}
-
function openWindow(aTarget)
{
target = aTarget;
-
let deferred = promise.defer();
-
- let win = Services.ww.openWindow(null, Tools.webConsole.url, "_blank",
+ // Using the old frontend for now in the browser console. This can be switched to
+ // Tools.webConsole.url to use whatever is preffed on.
+ let url = Tools.webConsole.oldWebConsoleURL;
+ let win = Services.ww.openWindow(null, url, "_blank",
BROWSER_CONSOLE_WINDOW_FEATURES, null);
win.addEventListener("DOMContentLoaded", function () {
- // Set the correct Browser Console title.
- let root = win.document.documentElement;
- root.setAttribute("title", root.getAttribute("browserConsoleTitle"));
-
+ win.document.title = l10n.getStr("browserConsole.title");
deferred.resolve(win);
}, {once: true});
-
return deferred.promise;
}
-
connect().then(getTarget).then(openWindow).then((aWindow) => {
return this.openBrowserConsole(target, aWindow, aWindow)
.then((aBrowserConsole) => {
this._browserConsoleDefer.resolve(aBrowserConsole);
this._browserConsoleDefer = null;
});
}, console.error.bind(console));
@@ -279,27 +272,27 @@ HUD_SERVICE.prototype =
* The window of the web console owner.
*/
function WebConsole(aTarget, aIframeWindow, aChromeWindow)
{
this.iframeWindow = aIframeWindow;
this.chromeWindow = aChromeWindow;
this.hudId = "hud_" + ++gHudId;
this.target = aTarget;
-
this.browserWindow = this.chromeWindow.top;
-
let element = this.browserWindow.document.documentElement;
if (element.getAttribute("windowtype") != gDevTools.chromeWindowType) {
this.browserWindow = HUDService.currentContext();
}
-
- this.ui = new WebConsoleFrame(this);
+ if (aIframeWindow.location.href === Tools.webConsole.newWebConsoleURL) {
+ this.ui = new NewWebConsoleFrame(this);
+ } else {
+ this.ui = new WebConsoleFrame(this);
+ }
}
-
WebConsole.prototype = {
iframeWindow: null,
chromeWindow: null,
browserWindow: null,
hudId: null,
target: null,
ui: null,
_browserConsole: false,
--- a/devtools/client/webconsole/jsterm.js
+++ b/devtools/client/webconsole/jsterm.js
@@ -251,20 +251,22 @@ JSTerm.prototype = {
};
let doc = this.hud.document;
let toolbox = gDevTools.getToolbox(this.hud.owner.target);
let tooltipDoc = toolbox ? toolbox.doc : doc;
// The popup will be attached to the toolbox document or HUD document in the case
// such as the browser console which doesn't have a toolbox.
this.autocompletePopup = new AutocompletePopup(tooltipDoc, autocompleteOptions);
-
let inputContainer = doc.querySelector(".jsterm-input-container");
this.completeNode = doc.querySelector(".jsterm-complete-node");
this.inputNode = doc.querySelector(".jsterm-input-node");
+ // Update the character width and height needed for the popup offset
+ // calculations.
+ this._updateCharSize();
if (this.hud.isBrowserConsole &&
!Services.prefs.getBoolPref("devtools.chrome.enabled")) {
inputContainer.style.display = "none";
} else {
let okstring = l10n.getStr("selfxss.okstring");
let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
this._onPaste = WebConsoleUtils.pasteHandlerGen(
@@ -584,16 +586,21 @@ JSTerm.prototype = {
* option is not used, then the variables view opens in the sidebar.
* - autofocus: optional boolean, |true| if you want to give focus to
* the variables view window after open, |false| otherwise.
* @return object
* A promise object that is resolved when the variables view has
* opened. The new variables view instance is given to the callbacks.
*/
openVariablesView: function (options) {
+ // Bail out if the side bar doesn't exist.
+ if (!this.hud.document.querySelector("#webconsole-sidebar")) {
+ return Promise.resolve(null);
+ }
+
let onContainerReady = (window) => {
let container = window.document.querySelector("#variables");
let view = this._variablesView;
if (!view || options.targetElement) {
let viewOptions = {
container: container,
hideFilterInput: options.hideFilterInput,
};
@@ -942,41 +949,39 @@ JSTerm.prototype = {
* This method emits the "messages-cleared" notification.
*
* @param boolean clearStorage
* True if you want to clear the console messages storage associated to
* this Web Console.
*/
clearOutput: function (clearStorage) {
let hud = this.hud;
- let outputNode = hud.outputNode;
- let node;
- while ((node = outputNode.firstChild)) {
- hud.removeOutputMessage(node);
- }
- hud.groupDepth = 0;
- hud._outputQueue.forEach(hud._destroyItem, hud);
- hud._outputQueue = [];
+ if (hud.NEW_CONSOLE_OUTPUT_ENABLED) {
+ hud.newConsoleOutput.dispatchMessagesClear();
+ } else {
+ let outputNode = hud.outputNode;
+ let node;
+ while ((node = outputNode.firstChild)) {
+ hud.removeOutputMessage(node);
+ }
+
+ hud.groupDepth = 0;
+ hud._outputQueue.forEach(hud._destroyItem, hud);
+ hud._outputQueue = [];
+ hud._repeatNodes = {};
+ }
this.webConsoleClient.clearNetworkRequests();
- hud._repeatNodes = {};
-
if (clearStorage) {
this.webConsoleClient.clearMessagesCache();
}
-
this._sidebarDestroy();
-
- if (hud.NEW_CONSOLE_OUTPUT_ENABLED) {
- hud.newConsoleOutput.dispatchMessagesClear();
- }
-
+ this.focus();
this.emit("messages-cleared");
},
-
/**
* Remove all of the private messages from the Web Console output.
*
* This method emits the "private-messages-cleared" notification.
*/
clearPrivateMessages: function () {
let nodes = this.hud.outputNode.querySelectorAll(".message[private]");
for (let node of nodes) {
@@ -1586,28 +1591,26 @@ JSTerm.prototype = {
let popup = this.autocompletePopup;
popup.setItems(items);
let completionType = this.lastCompletion.completionType;
this.lastCompletion = {
value: inputValue,
matchProp: lastPart,
};
-
if (items.length > 1 && !popup.isOpen) {
let str = this.getInputValue().substr(0, this.inputNode.selectionStart);
let offset = str.length - (str.lastIndexOf("\n") + 1) - lastPart.length;
- let x = offset * this.hud._inputCharWidth;
- popup.openPopup(inputNode, x + this.hud._chevronWidth);
+ let x = offset * this._inputCharWidth;
+ popup.openPopup(inputNode, x + this._chevronWidth);
this._autocompletePopupNavigated = false;
} else if (items.length < 2 && popup.isOpen) {
popup.hidePopup();
this._autocompletePopupNavigated = false;
}
-
if (items.length == 1) {
popup.selectedIndex = 0;
}
this.onAutocompleteSelect();
if (completionType != this.COMPLETE_HINT_ONLY && popup.itemCount == 1) {
this.acceptProposedCompletion();
@@ -1691,16 +1694,41 @@ JSTerm.prototype = {
* @param string suffix
* The proposed suffix for the inputNode value.
*/
updateCompleteNode: function (suffix) {
// completion prefix = input, with non-control chars replaced by spaces
let prefix = suffix ? this.getInputValue().replace(/[\S]/g, " ") : "";
this.completeNode.value = prefix + suffix;
},
+ /**
+ * Calculates the width and height of a single character of the input box.
+ * This will be used in opening the popup at the correct offset.
+ *
+ * @private
+ */
+ _updateCharSize: function () {
+ let doc = this.hud.document;
+ let tempLabel = doc.createElementNS(XHTML_NS, "span");
+ let style = tempLabel.style;
+ style.position = "fixed";
+ style.padding = "0";
+ style.margin = "0";
+ style.width = "auto";
+ style.color = "transparent";
+ WebConsoleUtils.copyTextStyles(this.inputNode, tempLabel);
+ tempLabel.textContent = "x";
+ doc.documentElement.appendChild(tempLabel);
+ this._inputCharWidth = tempLabel.offsetWidth;
+ tempLabel.remove();
+ // Calculate the width of the chevron placed at the beginning of the input
+ // box. Remove 4 more pixels to accomodate the padding of the popup.
+ this._chevronWidth = +doc.defaultView.getComputedStyle(this.inputNode)
+ .paddingLeft.replace(/[^0-9.]/g, "") - 4;
+ },
/**
* Destroy the sidebar.
* @private
*/
_sidebarDestroy: function () {
if (this._variablesView) {
this._variablesView.controller.releaseActors();
--- a/devtools/client/webconsole/moz.build
+++ b/devtools/client/webconsole/moz.build
@@ -5,23 +5,22 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
DIRS += [
'net',
'new-console-output',
]
-
DevToolsModules(
'console-commands.js',
'console-output.js',
'hudservice.js',
'jsterm.js',
+ 'new-webconsole.js',
'panel.js',
'utils.js',
'webconsole-connection-proxy.js',
'webconsole-l10n.js',
'webconsole.js',
)
-
with Files('**'):
BUG_COMPONENT = ('Firefox', 'Developer Tools: Console')
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -29,22 +29,42 @@ function NewConsoleOutputWrapper(parentN
this.toolbox = toolbox;
this.owner = owner;
this.document = document;
this.init = this.init.bind(this);
store = configureStore(this.jsterm.hud);
}
-
NewConsoleOutputWrapper.prototype = {
init: function () {
const attachRefToHud = (id, node) => {
this.jsterm.hud[id] = node;
};
+ // Focus the input line whenever the output area is clicked.
+ this.parentNode.addEventListener("click", (event) => {
+ // Do not focus on middle/right-click or 2+ clicks.
+ if (event.detail !== 1 || event.button !== 0) {
+ return;
+ }
+
+ // Do not focus if something is selected
+ let selection = this.document.defaultView.getSelection();
+ if (selection && !selection.isCollapsed) {
+ return;
+ }
+
+ // Do not focus if a link was clicked
+ if (event.target.nodeName.toLowerCase() === "a" ||
+ event.target.parentNode.nodeName.toLowerCase() === "a") {
+ return;
+ }
+
+ this.jsterm.focus();
+ });
const serviceContainer = {
attachRefToHud,
emitNewMessage: (node, messageId) => {
this.jsterm.hud.emit("new-messages", new Set([{
node,
messageId,
}]));
@@ -135,24 +155,23 @@ NewConsoleOutputWrapper.prototype = {
let provider = React.createElement(
Provider,
{ store },
React.DOM.div(
{className: "webconsole-output-wrapper"},
filterBar,
childComponent
));
+ this.body = ReactDOM.render(provider, this.parentNode);
- this.body = ReactDOM.render(provider, this.parentNode);
+ this.jsterm.focus();
},
-
dispatchMessageAdd: function (message, waitForResponse) {
let action = actions.messageAdd(message);
batchedMessageAdd(action);
-
// Wait for the message to render to resolve with the DOM node.
// This is just for backwards compatibility with old tests, and should
// be removed once it's not needed anymore.
// Can only wait for response if the action contains a valid message.
if (waitForResponse && action.message) {
let messageId = action.message.id;
return new Promise(resolve => {
let jsterm = this.jsterm;
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_jsterm_inspect.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_jsterm_inspect.js
@@ -16,17 +16,17 @@ add_task(async function () {
let jsterm = hud.jsterm;
info("Test `inspect(window)`");
// Add a global value so we can check it later.
await jsterm.execute("testProp = 'testValue'");
await jsterm.execute("inspect(window)");
const inspectWindowNode = await waitFor(() =>
- findInspectResultMessage(hud.ui.experimentalOutputNode, 1));
+ findInspectResultMessage(hud.ui.outputNode, 1));
let objectInspectors = [...inspectWindowNode.querySelectorAll(".tree")];
is(objectInspectors.length, 1, "There is the expected number of object inspectors");
const [windowOi] = objectInspectors;
let windowOiNodes = windowOi.querySelectorAll(".node");
// The tree can be collapsed since the properties are fetched asynchronously.
@@ -48,15 +48,15 @@ add_task(async function () {
is(testPropertyValueNode.textContent, '"testValue"',
"The testProp property value is displayed as expected");
/* Check that a primitive value can be inspected, too */
info("Test `inspect(1)`");
await jsterm.execute("inspect(1)");
const inspectPrimitiveNode = await waitFor(() =>
- findInspectResultMessage(hud.ui.experimentalOutputNode, 2));
+ findInspectResultMessage(hud.ui.outputNode, 2));
is(inspectPrimitiveNode.textContent, 1, "The primitive is displayed as expected");
});
function findInspectResultMessage(node, index) {
return node.querySelectorAll(".message.result")[index];
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_dir.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_dir.js
@@ -25,25 +25,22 @@ add_task(async function () {
});
info("console.dir on an array");
await ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
content.wrappedJSObject.console.dir(
[1, 2, {a: "a", b: "b"}],
);
});
-
let dirMessageNode = await waitFor(() =>
- findConsoleDir(hud.ui.experimentalOutputNode, 0));
+ findConsoleDir(hud.ui.outputNode, 0));
let objectInspectors = [...dirMessageNode.querySelectorAll(".tree")];
is(objectInspectors.length, 1, "There is the expected number of object inspectors");
-
const [arrayOi] = objectInspectors;
let arrayOiNodes = arrayOi.querySelectorAll(".node");
-
// The tree can be collapsed since the properties are fetched asynchronously.
if (arrayOiNodes.length === 1) {
// If this is the case, we wait for the properties to be fetched and displayed.
await waitForNodeMutation(arrayOi, {
childList: true
});
arrayOiNodes = arrayOi.querySelectorAll(".node");
}
@@ -55,28 +52,24 @@ add_task(async function () {
const arrayPropertiesNames = ["0", "1", "2", "length", "__proto__"];
is(JSON.stringify(propertiesNodes), JSON.stringify(arrayPropertiesNames));
info("console.dir on a long object");
const obj = Array.from({length: 100}).reduce((res, _, i) => {
res["item-" + (i + 1).toString().padStart(3, "0")] = i + 1;
return res;
}, {});
-
await ContentTask.spawn(gBrowser.selectedBrowser, obj, function (data) {
content.wrappedJSObject.console.dir(data);
});
-
- dirMessageNode = await waitFor(() => findConsoleDir(hud.ui.experimentalOutputNode, 1));
+ dirMessageNode = await waitFor(() => findConsoleDir(hud.ui.outputNode, 1));
objectInspectors = [...dirMessageNode.querySelectorAll(".tree")];
is(objectInspectors.length, 1, "There is the expected number of object inspectors");
-
const [objectOi] = objectInspectors;
let objectOiNodes = objectOi.querySelectorAll(".node");
-
// The tree can be collapsed since the properties are fetched asynchronously.
if (objectOiNodes.length === 1) {
// If this is the case, we wait for the properties to be fetched and displayed.
await waitForNodeMutation(objectOi, {
childList: true
});
objectOiNodes = objectOi.querySelectorAll(".node");
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
@@ -65,27 +65,23 @@ add_task(function* () {
node = yield waitFor(() => findMessage(hud, "log-4"));
testClass(node, "log");
testIndent(node, 0);
info("Test a collapsed group at root level");
node = yield waitFor(() => findMessage(hud, "group-3"));
testClass(node, "startGroupCollapsed");
testIndent(node, 0);
-
info("Test a message at root level, after closing a collapsed group");
node = yield waitFor(() => findMessage(hud, "log-6"));
testClass(node, "log");
testIndent(node, 0);
-
- let nodes = hud.ui.experimentalOutputNode.querySelectorAll(".message");
+ let nodes = hud.ui.outputNode.querySelectorAll(".message");
is(nodes.length, 8, "expected number of messages are displayed");
});
-
function testClass(node, className) {
ok(node.classList.contains(className), `message has the expected "${className}" class`);
}
-
function testIndent(node, indent) {
indent = `${indent * INDENT_WIDTH}px`;
is(node.querySelector(".indent").style.width, indent,
"message has the expected level of indentation");
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_table.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_table.js
@@ -117,34 +117,29 @@ add_task(function* () {
}
}];
yield ContentTask.spawn(gBrowser.selectedBrowser, testCases, function (tests) {
tests.forEach((test) => {
content.wrappedJSObject.doConsoleTable(test.input, test.headers);
});
});
-
let nodes = [];
for (let testCase of testCases) {
let node = yield waitFor(
- () => findConsoleTable(hud.ui.experimentalOutputNode, testCases.indexOf(testCase))
+ () => findConsoleTable(hud.ui.outputNode, testCases.indexOf(testCase))
);
nodes.push(node);
}
-
- let consoleTableNodes = hud.ui.experimentalOutputNode.querySelectorAll(
+ let consoleTableNodes = hud.ui.outputNode.querySelectorAll(
".message .new-consoletable");
-
is(consoleTableNodes.length, testCases.length,
"console has the expected number of consoleTable items");
-
testCases.forEach((testCase, index) => testItem(testCase, nodes[index]));
});
-
function testItem(testCase, node) {
info(testCase.info);
let columns = Array.from(node.querySelectorAll("thead th"));
let rows = Array.from(node.querySelectorAll("tbody tr"));
is(
JSON.stringify(testCase.expected.columns),
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_filters.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_filters.js
@@ -1,30 +1,25 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests filters.
"use strict";
-
const { MESSAGE_LEVEL } = require("devtools/client/webconsole/new-console-output/constants");
-
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-console-filters.html";
-
add_task(function* () {
let hud = yield openNewTabAndConsole(TEST_URI);
- const outputNode = hud.ui.experimentalOutputNode;
-
+ const outputNode = hud.ui.outputNode;
const toolbar = yield waitFor(() => {
return outputNode.querySelector(".webconsole-filterbar-primary");
});
ok(toolbar, "Toolbar found");
-
// Show the filter bar
toolbar.querySelector(".devtools-filter-icon").click();
const filterBar = yield waitFor(() => {
return outputNode.querySelector(".webconsole-filterbar-secondary");
});
ok(filterBar, "Filter bar is shown when filter icon is clicked.");
// Check defaults.
@@ -46,27 +41,24 @@ add_task(function* () {
filterBar.querySelector(".error").click();
yield waitFor(() => findMessages(hud, "").length == 4);
ok(true, "When a filter is turned off, its messages are not shown.");
// Check that the ui settings were persisted.
yield closeTabAndToolbox();
yield testFilterPersistence();
});
-
function filterIsEnabled(button) {
return button.classList.contains("checked");
}
-
function* testFilterPersistence() {
let hud = yield openNewTabAndConsole(TEST_URI);
- const outputNode = hud.ui.experimentalOutputNode;
+ const outputNode = hud.ui.outputNode;
const filterBar = yield waitFor(() => {
return outputNode.querySelector(".webconsole-filterbar-secondary");
});
ok(filterBar, "Filter bar ui setting is persisted.");
-
// Check that the filter settings were persisted.
ok(!filterIsEnabled(filterBar.querySelector(".error")),
"Filter button setting is persisted");
ok(findMessages(hud, "").length == 4,
"Messages of all levels shown when filters are on.");
}
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_filters_persist.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_filters_persist.js
@@ -35,29 +35,25 @@ add_task(function* () {
yield closeTabAndToolbox();
hud = yield openNewTabAndConsole(TEST_URI);
info("Check that all filters are enabled");
filterButtons = yield getFilterButtons(hud);
filterButtons.forEach(filterButton => {
ok(filterIsEnabled(filterButton), "filter is enabled");
});
-
// Check that the ui settings were persisted.
yield closeTabAndToolbox();
});
-
function* getFilterButtons(hud) {
- const outputNode = hud.ui.experimentalOutputNode;
-
+ const outputNode = hud.ui.outputNode;
info("Wait for console toolbar to appear");
const toolbar = yield waitFor(() => {
return outputNode.querySelector(".webconsole-filterbar-primary");
});
-
// Show the filter bar if it is hidden
if (!outputNode.querySelector(".webconsole-filterbar-secondary")) {
toolbar.querySelector(".devtools-filter-icon").click();
}
info("Wait for console filterbar to appear");
const filterBar = yield waitFor(() => {
return outputNode.querySelector(".webconsole-filterbar-secondary");
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
@@ -20,31 +20,26 @@ add_task(function* () {
let inputNode = hud.jsterm.inputNode;
ok(inputNode.getAttribute("focused"), "input node is focused after output is cleared");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
content.wrappedJSObject.console.log("console message 2");
});
let msg = yield waitFor(() => findMessage(hud, "console message 2"));
let outputItem = msg.querySelector(".message-body");
-
inputNode = hud.jsterm.inputNode;
ok(inputNode.getAttribute("focused"), "input node is focused, first");
-
yield waitForBlurredInput(inputNode);
-
EventUtils.sendMouseEvent({type: "click"}, hud.outputNode);
+
ok(inputNode.getAttribute("focused"), "input node is focused, second time");
-
yield waitForBlurredInput(inputNode);
-
info("Setting a text selection and making sure a click does not re-focus");
let selection = hud.iframeWindow.getSelection();
selection.selectAllChildren(outputItem);
-
EventUtils.sendMouseEvent({type: "click"}, hud.outputNode);
ok(!inputNode.getAttribute("focused"),
"input node focused after text is selected");
});
function waitForBlurredInput(inputNode) {
return new Promise(resolve => {
let lostFocus = () => {
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
@@ -14,31 +14,25 @@ const TEST_URI =
console.log("console message " + i);
}
</script>
`;
add_task(function* () {
let hud = yield openNewTabAndConsole(TEST_URI);
info("Web Console opened");
-
const outputScroller = hud.ui.outputScroller;
-
yield waitFor(() => findMessages(hud, "").length == 100);
-
let currentPosition = outputScroller.scrollTop;
const bottom = currentPosition;
-
- EventUtils.sendMouseEvent({type: "click"}, hud.jsterm.inputNode);
-
+ hud.jsterm.inputNode.focus();
// Page up.
EventUtils.synthesizeKey("VK_PAGE_UP", {});
isnot(outputScroller.scrollTop, currentPosition,
"scroll position changed after page up");
-
// Page down.
currentPosition = outputScroller.scrollTop;
EventUtils.synthesizeKey("VK_PAGE_DOWN", {});
ok(outputScroller.scrollTop > currentPosition,
"scroll position now at bottom");
// Home
EventUtils.synthesizeKey("VK_HOME", {});
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -131,24 +131,23 @@ function findMessage(hud, text, selector
* @param object hud
* The web console.
* @param string text
* A substring that can be found in the message.
* @param selector [optional]
* The selector to use in finding the message.
*/
function findMessages(hud, text, selector = ".message") {
- const messages = hud.ui.experimentalOutputNode.querySelectorAll(selector);
+ const messages = hud.ui.outputNode.querySelectorAll(selector);
const elements = Array.prototype.filter.call(
messages,
(el) => el.textContent.includes(text)
);
return elements;
}
-
/**
* Simulate a context menu event on the provided element, and wait for the console context
* menu to open. Returns a promise that resolves the menu popup element.
*
* @param object hud
* The web console.
* @param element element
* The dom element on which the context menu event should be synthesized.
--- a/devtools/client/webconsole/new-webconsole.js
+++ b/devtools/client/webconsole/new-webconsole.js
@@ -9,23 +9,24 @@
const {Utils: WebConsoleUtils} = require("devtools/client/webconsole/utils");
const EventEmitter = require("devtools/shared/event-emitter");
const promise = require("promise");
const defer = require("devtools/shared/defer");
const Services = require("Services");
const { gDevTools } = require("devtools/client/framework/devtools");
const { JSTerm } = require("devtools/client/webconsole/jsterm");
const { WebConsoleConnectionProxy } = require("devtools/client/webconsole/webconsole-connection-proxy");
-
+const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
+const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
+const system = require("devtools/shared/system");
+const { ZoomKeys } = require("devtools/client/shared/zoom-keys");
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
-
// XXX: This file is incomplete (see bug 1326937).
// It's used when loading the webconsole with devtools-launchpad, but will ultimately be
// the entry point for the new frontend
-
/**
* A WebConsoleFrame instance is an interactive console initialized *per target*
* that displays console log data as well as provides an interactive terminal to
* manipulate the target's document content.
*
* The WebConsoleFrame is responsible for the actual Web Console UI
* implementation.
*
@@ -77,26 +78,36 @@ NewWebConsoleFrame.prototype = {
Services.obs.notifyObservers(id, "web-console-created");
}
};
allReady.then(notifyObservers, notifyObservers)
.then(this.newConsoleOutput.init);
return allReady;
},
-
destroy() {
if (this._destroyer) {
return this._destroyer.promise;
}
-
this._destroyer = defer();
+ Services.prefs.removeObserver(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
+ this.React = this.ReactDOM = this.FrameView = null;
+ if (this.jsterm) {
+ this.jsterm.off("sidebar-opened", this.resize);
+ this.jsterm.off("sidebar-closed", this.resize);
+ this.jsterm.destroy();
+ this.jsterm = null;
+ }
- Services.prefs.addObserver(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
- this.React = this.ReactDOM = this.FrameView = null;
+ let toolbox = gDevTools.getToolbox(this.owner.target);
+ if (toolbox) {
+ toolbox.off("webconsole-selected", this._onPanelSelected);
+ }
+
+ this.window = this.owner = this.newConsoleOutput = null;
let onDestroy = () => {
this._destroyer.resolve(null);
};
if (this.proxy) {
this.proxy.disconnect().then(onDestroy);
this.proxy = null;
} else {
@@ -194,22 +205,50 @@ NewWebConsoleFrame.prototype = {
this.window.jsterm = this.jsterm;
// @TODO Once the toolbox has been converted to React, see if passing
// in JSTerm is still necessary.
// Handle both launchpad and toolbox loading
let Wrapper = this.owner.NewConsoleOutputWrapper || this.window.NewConsoleOutput;
this.newConsoleOutput = new Wrapper(
this.outputNode, this.jsterm, toolbox, this.owner, this.document);
-
// Toggle the timestamp on preference change
Services.prefs.addObserver(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
this._onToolboxPrefChanged();
+
+ this._initShortcuts();
},
+ _initShortcuts: function () {
+ let shortcuts = new KeyShortcuts({
+ window: this.window
+ });
+
+ shortcuts.on(l10n.getStr("webconsole.find.key"),
+ (name, event) => {
+ this.filterBox.focus();
+ event.preventDefault();
+ });
+
+ let clearShortcut;
+ if (system.constants.platform === "macosx") {
+ clearShortcut = l10n.getStr("webconsole.clear.keyOSX");
+ } else {
+ clearShortcut = l10n.getStr("webconsole.clear.key");
+ }
+
+ shortcuts.on(clearShortcut, () => this.jsterm.clearOutput(true));
+
+ if (this.isBrowserConsole) {
+ shortcuts.on(l10n.getStr("webconsole.close.key"),
+ this.window.close.bind(this.window));
+
+ ZoomKeys.register(this.window);
+ }
+ },
/**
* Handler for page location changes.
*
* @param string uri
* New page location.
* @param string title
* New page title.
*/
--- a/devtools/client/webconsole/test/browser_console_open_or_focus.js
+++ b/devtools/client/webconsole/test/browser_console_open_or_focus.js
@@ -21,26 +21,20 @@ add_task(function* () {
console.log("testmessage");
yield waitForMessages({
webconsole: hud,
messages: [{
text: "testmessage"
}],
});
-
currWindow = Services.wm.getMostRecentWindow(null);
- is(currWindow.document.documentURI, Tools.webConsole.url,
+ is(currWindow.document.documentURI, Tools.webConsole.oldWebConsoleURL,
"The Browser Console is open and has focus");
-
mainWindow.focus();
-
yield HUDService.openBrowserConsoleOrFocus();
-
currWindow = Services.wm.getMostRecentWindow(null);
- is(currWindow.document.documentURI, Tools.webConsole.url,
+ is(currWindow.document.documentURI, Tools.webConsole.oldWebConsoleURL,
"The Browser Console is open and has focus");
-
yield HUDService.toggleBrowserConsole();
-
hud = HUDService.getBrowserConsole();
ok(!hud, "Browser Console has been closed");
});
--- a/devtools/client/webconsole/webconsole-connection-proxy.js
+++ b/devtools/client/webconsole/webconsole-connection-proxy.js
@@ -282,145 +282,156 @@ WebConsoleConnectionProxy.prototype = {
*
* @private
* @param string type
* Message type.
* @param object packet
* The message received from the server.
*/
_onPageError: function (type, packet) {
- if (this.webConsoleFrame && packet.from == this._consoleActor) {
- if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.dispatchMessageAdd(packet);
- return;
- }
+ if (!this.webConsoleFrame || packet.from != this._consoleActor) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ this.dispatchMessageAdd(packet);
+ } else {
this.webConsoleFrame.handlePageError(packet.pageError);
}
},
-
/**
* The "logMessage" message type handler. We redirect any message to the UI
* for displaying.
*
* @private
* @param string type
* Message type.
* @param object packet
* The message received from the server.
*/
_onLogMessage: function (type, packet) {
if (!this.webConsoleFrame || packet.from != this._consoleActor) {
return;
}
-
if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
this.dispatchMessageAdd(packet);
} else {
this.webConsoleFrame.handleLogMessage(packet);
}
},
-
/**
* The "consoleAPICall" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
* @param string type
* Message type.
* @param object packet
* The message received from the server.
*/
_onConsoleAPICall: function (type, packet) {
- if (this.webConsoleFrame && packet.from == this._consoleActor) {
- if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.dispatchMessageAdd(packet);
- } else {
- this.webConsoleFrame.handleConsoleAPICall(packet.message);
- }
+ if (!this.webConsoleFrame || packet.from != this._consoleActor) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ this.dispatchMessageAdd(packet);
+ } else {
+ this.webConsoleFrame.handleConsoleAPICall(packet.message);
}
},
-
/**
* The "networkEvent" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
* @param string type
* Message type.
* @param object networkInfo
* The network request information.
*/
_onNetworkEvent: function (type, networkInfo) {
- if (this.webConsoleFrame) {
- if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.dispatchMessageAdd(networkInfo);
- } else {
- this.webConsoleFrame.handleNetworkEvent(networkInfo);
- }
+ if (!this.webConsoleFrame) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ this.dispatchMessageAdd(networkInfo);
+ } else {
+ this.webConsoleFrame.handleNetworkEvent(networkInfo);
}
},
-
/**
* The "networkEventUpdate" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
* @param string type
* Message type.
* @param object response
* The update response received from the server.
*/
_onNetworkEventUpdate: function (type, response) {
+ if (!this.webConsoleFrame) {
+ return;
+ }
let { packet, networkInfo } = response;
- if (this.webConsoleFrame) {
- if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.dispatchMessageUpdate(networkInfo, response);
- }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ this.dispatchMessageUpdate(networkInfo, response);
+ } else {
this.webConsoleFrame.handleNetworkEventUpdate(networkInfo, packet);
}
},
-
/**
* The "fileActivity" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
* @param string type
* Message type.
* @param object packet
* The message received from the server.
*/
_onFileActivity: function (type, packet) {
- if (this.webConsoleFrame && packet.from == this._consoleActor) {
+ if (!this.webConsoleFrame || packet.from != this._consoleActor) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ // TODO: Implement for new console
+ } else {
this.webConsoleFrame.handleFileActivity(packet.uri);
}
},
-
_onReflowActivity: function (type, packet) {
- if (this.webConsoleFrame && packet.from == this._consoleActor) {
+ if (!this.webConsoleFrame || packet.from != this._consoleActor) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ // TODO: Implement for new console
+ } else {
this.webConsoleFrame.handleReflowActivity(packet);
}
},
-
/**
* The "serverLogCall" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
* @param string type
* Message type.
* @param object packet
* The message received from the server.
*/
_onServerLogCall: function (type, packet) {
- if (this.webConsoleFrame && packet.from == this._consoleActor) {
+ if (!this.webConsoleFrame || packet.from != this._consoleActor) {
+ return;
+ }
+ if (this.webConsoleFrame.NEW_CONSOLE_OUTPUT_ENABLED) {
+ // TODO: Implement for new console
+ } else {
this.webConsoleFrame.handleConsoleAPICall(packet.message);
}
},
-
/**
* The "lastPrivateContextExited" message type handler. When this message is
* received the Web Console UI is cleared.
*
* @private
* @param string type
* Message type.
* @param object packet
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -485,24 +485,18 @@ WebConsoleFrame.prototype = {
// This notification is only used in tests. Don't chain it onto
// the returned promise because the console panel needs to be attached
// to the toolbox before the web-console-created event is receieved.
let notifyObservers = () => {
let id = WebConsoleUtils.supportsString(this.hudId);
Services.obs.notifyObservers(id, "web-console-created");
};
allReady.then(notifyObservers, notifyObservers);
-
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- allReady.then(this.newConsoleOutput.init);
- }
-
return allReady;
},
-
/**
* Connect to the server using the remote debugging protocol.
*
* @private
* @return object
* A promise object that is resolved/reject based on the connection
* result.
*/
@@ -522,92 +516,54 @@ WebConsoleFrame.prototype = {
let node = this.createMessageNode(CATEGORY_JS, SEVERITY_ERROR,
reason.error + ": " + reason.message);
this.outputMessage(CATEGORY_JS, node, [reason]);
this._initDefer.reject(reason);
});
return this._initDefer.promise;
},
-
/**
* Find the Web Console UI elements and setup event listeners as needed.
* @private
*/
_initUI: function () {
this.document = this.window.document;
this.rootElement = this.document.documentElement;
- this.NEW_CONSOLE_OUTPUT_ENABLED = !this.isBrowserConsole
- && !this.owner.target.chrome
- && Services.prefs.getBoolPref(PREF_NEW_FRONTEND_ENABLED);
-
this.outputNode = this.document.getElementById("output-container");
this.outputWrapper = this.document.getElementById("output-wrapper");
this.completeNode = this.document.querySelector(".jsterm-complete-node");
this.inputNode = this.document.querySelector(".jsterm-input-node");
-
// In the old frontend, the area that scrolls is outputWrapper, but in the new
// frontend this will be reassigned.
this.outputScroller = this.outputWrapper;
-
- // Update the character width and height needed for the popup offset
- // calculations.
- this._updateCharSize();
-
this.jsterm = new JSTerm(this);
this.jsterm.init();
-
let toolbox = gDevTools.getToolbox(this.owner.target);
-
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- // @TODO Remove this once JSTerm is handled with React/Redux.
- this.window.jsterm = this.jsterm;
-
- // Remove context menu for now (see Bug 1307239).
- this.outputWrapper.removeAttribute("context");
-
- // XXX: We should actually stop output from happening on old output
- // panel, but for now let's just hide it.
- this.experimentalOutputNode = this.outputNode.cloneNode();
- this.experimentalOutputNode.removeAttribute("tabindex");
- this.outputNode.hidden = true;
- this.outputNode.parentNode.appendChild(this.experimentalOutputNode);
- // @TODO Once the toolbox has been converted to React, see if passing
- // in JSTerm is still necessary.
-
- this.newConsoleOutput = new this.window.NewConsoleOutput(
- this.experimentalOutputNode, this.jsterm, toolbox, this.owner, this.document);
-
- let filterToolbar = this.document.querySelector(".hud-console-filter-toolbar");
- filterToolbar.hidden = true;
- } else {
- // Register the controller to handle "select all" properly.
- this._commandController = new CommandController(this);
- this.window.controllers.insertControllerAt(0, this._commandController);
-
- this._contextMenuHandler = new ConsoleContextMenu(this);
-
- this._initDefaultFilterPrefs();
- this.filterBox = this.document.querySelector(".hud-filter-box");
- this._setFilterTextBoxEvents();
- this._initFilterButtons();
- let clearButton =
- this.document.getElementsByClassName("webconsole-clear-console-button")[0];
- clearButton.addEventListener("command", () => {
- this.owner._onClearButton();
- this.jsterm.clearOutput(true);
- });
-
- }
-
+ // Register the controller to handle "select all" properly.
+ this._commandController = new CommandController(this);
+ this.window.controllers.insertControllerAt(0, this._commandController);
+
+ this._contextMenuHandler = new ConsoleContextMenu(this);
+
+ this._initDefaultFilterPrefs();
+ this.filterBox = this.document.querySelector(".hud-filter-box");
+ this._setFilterTextBoxEvents();
+ this._initFilterButtons();
+
+ let clearButton =
+ this.document.getElementsByClassName("webconsole-clear-console-button")[0];
+ clearButton.addEventListener("command", () => {
+ this.owner._onClearButton();
+ this.jsterm.clearOutput(true);
+ });
this.resize();
this.window.addEventListener("resize", this.resize, true);
this.jsterm.on("sidebar-opened", this.resize);
this.jsterm.on("sidebar-closed", this.resize);
-
if (toolbox) {
toolbox.on("webconsole-selected", this._onPanelSelected);
}
/*
* Focus the input line whenever the output area is clicked.
*/
this.outputWrapper.addEventListener("click", (event) => {
@@ -616,58 +572,40 @@ WebConsoleFrame.prototype = {
return;
}
// Do not focus if something is selected
let selection = this.window.getSelection();
if (selection && !selection.isCollapsed) {
return;
}
-
// Do not focus if a link was clicked
if (event.target.nodeName.toLowerCase() === "a" ||
event.target.parentNode.nodeName.toLowerCase() === "a") {
return;
}
-
- // Do not focus if a search input was clicked on the new frontend
- if (this.NEW_CONSOLE_OUTPUT_ENABLED &&
- event.target.nodeName.toLowerCase() === "input" &&
- event.target.getAttribute("type").toLowerCase() === "search") {
- return;
- }
-
this.jsterm.focus();
});
-
// Toggle the timestamp on preference change
this._prefObserver = new PrefObserver("");
this._prefObserver.on(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
this._onToolboxPrefChanged();
-
this._initShortcuts();
// focus input node
this.jsterm.focus();
},
-
/**
* Resizes the output node to fit the output wrapped.
* We need this because it makes the layout a lot faster than
* using -moz-box-flex and 100% width. See Bug 1237368.
*/
resize: function () {
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.experimentalOutputNode.style.width =
- this.outputWrapper.clientWidth + "px";
- } else {
- this.outputNode.style.width = this.outputWrapper.clientWidth + "px";
- }
+ this.outputNode.style.width = this.outputWrapper.clientWidth + "px";
},
-
/**
* Sets the focus to JavaScript input field when the web console tab is
* selected or when there is a split console present.
* @private
*/
_onPanelSelected: function () {
this.jsterm.focus();
},
@@ -832,49 +770,21 @@ WebConsoleFrame.prototype = {
if (Services.appinfo.OS == "Darwin") {
let net = this.document.querySelector("toolbarbutton[category=net]");
let accesskey = net.getAttribute("accesskeyMacOSX");
net.setAttribute("accesskey", accesskey);
let logging =
this.document.querySelector("toolbarbutton[category=logging]");
logging.removeAttribute("accesskey");
-
let serverLogging =
this.document.querySelector("toolbarbutton[category=server]");
serverLogging.removeAttribute("accesskey");
}
},
-
- /**
- * Calculates the width and height of a single character of the input box.
- * This will be used in opening the popup at the correct offset.
- *
- * @private
- */
- _updateCharSize: function () {
- let doc = this.document;
- let tempLabel = doc.createElementNS(XHTML_NS, "span");
- let style = tempLabel.style;
- style.position = "fixed";
- style.padding = "0";
- style.margin = "0";
- style.width = "auto";
- style.color = "transparent";
- WebConsoleUtils.copyTextStyles(this.inputNode, tempLabel);
- tempLabel.textContent = "x";
- doc.documentElement.appendChild(tempLabel);
- this._inputCharWidth = tempLabel.offsetWidth;
- tempLabel.remove();
- // Calculate the width of the chevron placed at the beginning of the input
- // box. Remove 4 more pixels to accomodate the padding of the popup.
- this._chevronWidth = +doc.defaultView.getComputedStyle(this.inputNode)
- .paddingLeft.replace(/[^0-9.]/g, "") - 4;
- },
-
/**
* The event handler that is called whenever a user switches a filter on or
* off.
*
* @private
* @param nsIDOMEvent event
* The event that triggered the filter change.
*/
@@ -1969,29 +1879,22 @@ WebConsoleFrame.prototype = {
* @param string event
* Event name.
* @param object packet
* Notification packet received from the server.
*/
handleTabNavigated: function (event, packet) {
if (event == "will-navigate") {
if (this.persistLog) {
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- // Add a _type to hit convertCachedPacket.
- packet._type = true;
- this.newConsoleOutput.dispatchMessageAdd(packet);
- } else {
- let marker = new Messages.NavigationMarker(packet, Date.now());
- this.output.addMessage(marker);
- }
+ let marker = new Messages.NavigationMarker(packet, Date.now());
+ this.output.addMessage(marker);
} else {
this.jsterm.clearOutput();
}
}
-
if (packet.url) {
this.onLocationChange(packet.url, packet.title);
}
if (event == "navigate" && !packet.nativeConsoleAPI) {
this.logWarningAboutReplacedAPI();
}
},
@@ -2693,31 +2596,27 @@ WebConsoleFrame.prototype = {
return;
}
this._startX = this._startY = undefined;
callback.call(this, event);
});
},
-
/**
* Called when the message timestamp pref changes.
*/
_onToolboxPrefChanged: function () {
let newValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.newConsoleOutput.dispatchTimestampsToggle(newValue);
- } else if (newValue) {
+ if (newValue) {
this.outputNode.classList.remove("hideTimestamps");
} else {
this.outputNode.classList.add("hideTimestamps");
}
},
-
/**
* Copies the selected items to the system clipboard.
*
* @param object options
* - linkOnly:
* An optional flag to copy only URL without other meta-information.
* Default is false.
* - contextmenu:
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/webconsole.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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 html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" dir="">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link rel="stylesheet" href="chrome://devtools/skin/new-webconsole.css"/>
+ <script src="chrome://devtools/content/shared/theme-switching.js"></script>
+ <script type="application/javascript"
+ src="resource://devtools/client/webconsole/new-console-output/main.js"></script>
+ </head>
+ <body class="theme-sidebar" role="application">
+ <div id="app-wrapper" class="theme-body">
+ <div id="output-container" role="document" aria-live="polite"/>
+ <div id="jsterm-wrapper">
+ <xul:notificationbox id="webconsole-notificationbox">
+ <div class="jsterm-input-container" style="direction:ltr">
+ <xul:stack class="jsterm-stack-node" flex="1">
+ <xul:textbox class="jsterm-complete-node devtools-monospace"
+ multiline="true" rows="1" tabindex="-1"/>
+ <xul:textbox class="jsterm-input-node devtools-monospace"
+ multiline="true" rows="1" tabindex="0"
+ aria-autocomplete="list"/>
+ </xul:stack>
+ </div>
+ </xul:notificationbox>
+ </div>
+ </div>
+ </body>
+</html>
--- a/devtools/client/webconsole/webconsole.xul
+++ b/devtools/client/webconsole/webconsole.xul
@@ -14,21 +14,19 @@
<?xml-stylesheet href="chrome://devtools/skin/components-frame.css"
type="text/css"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="devtools-webconsole"
macanimationtype="document"
fullscreenbutton="true"
title="&window.title;"
- browserConsoleTitle="&browserConsole.title;"
windowtype="devtools:webconsole"
width="900" height="350"
persist="screenX screenY width height sizemode">
-
<script type="application/javascript"
src="chrome://devtools/content/shared/theme-switching.js"/>
<script type="application/javascript"
src="resource://devtools/client/webconsole/new-console-output/main.js"/>
<script type="text/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="text/javascript" src="resource://devtools/client/webconsole/net/main.js"/>
<script type="text/javascript"><![CDATA[
function goUpdateConsoleCommands() {