mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 768096 - Web Console remote debugging protocol support - Part 4: cleanups; r=robcee
This commit is contained in:
parent
5630504d5a
commit
7a9f69146a
@ -7,7 +7,6 @@ browser.jar:
|
||||
content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml)
|
||||
content/browser/devtools/markup-view.css (markupview/markup-view.css)
|
||||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
content/browser/devtools/HUDService-content.js (webconsole/HUDService-content.js)
|
||||
content/browser/devtools/webconsole.js (webconsole/webconsole.js)
|
||||
* content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
|
@ -8,9 +8,6 @@ const EXPORTED_SYMBOLS = [ "DeveloperToolbar" ];
|
||||
|
||||
const NS_XHTML = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
const WEBCONSOLE_CONTENT_SCRIPT_URL =
|
||||
"chrome://browser/content/devtools/HUDService-content.js";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/devtools/Commands.jsm");
|
||||
@ -26,6 +23,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "gcli",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
|
||||
"resource:///modules/devtools/CmdCmd.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
|
||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||
|
||||
/**
|
||||
* Due to a number of panel bugs we need a way to check if we are running on
|
||||
* Linux. See the comments for TooltipPanel and OutputPanel for further details.
|
||||
@ -56,7 +56,8 @@ function DeveloperToolbar(aChromeWindow, aToolbarElement)
|
||||
this._lastState = NOTIFICATIONS.HIDE;
|
||||
this._pendingShowCallback = undefined;
|
||||
this._pendingHide = false;
|
||||
this._errorsCount = {};
|
||||
this._errorsCount = Object.create(null);
|
||||
this._errorListeners = Object.create(null);
|
||||
this._webConsoleButton = this._doc
|
||||
.getElementById("developer-toolbar-webconsole");
|
||||
|
||||
@ -88,9 +89,6 @@ const NOTIFICATIONS = {
|
||||
*/
|
||||
DeveloperToolbar.prototype.NOTIFICATIONS = NOTIFICATIONS;
|
||||
|
||||
DeveloperToolbar.prototype._contentMessageListeners =
|
||||
["WebConsole:CachedMessages", "WebConsole:PageError"];
|
||||
|
||||
/**
|
||||
* Is the toolbar open?
|
||||
*/
|
||||
@ -285,21 +283,18 @@ DeveloperToolbar.prototype._initErrorsCount = function DT__initErrorsCount(aTab)
|
||||
return;
|
||||
}
|
||||
|
||||
let messageManager = aTab.linkedBrowser.messageManager;
|
||||
messageManager.loadFrameScript(WEBCONSOLE_CONTENT_SCRIPT_URL, true);
|
||||
let window = aTab.linkedBrowser.contentWindow;
|
||||
let listener = new PageErrorListener(window, {
|
||||
onPageError: this._onPageError.bind(this, tabId),
|
||||
});
|
||||
listener.init();
|
||||
|
||||
this._errorListeners[tabId] = listener;
|
||||
this._errorsCount[tabId] = 0;
|
||||
|
||||
this._contentMessageListeners.forEach(function(aName) {
|
||||
messageManager.addMessageListener(aName, this);
|
||||
}, this);
|
||||
let messages = listener.getCachedMessages();
|
||||
messages.forEach(this._onPageError.bind(this, tabId));
|
||||
|
||||
let message = {
|
||||
features: ["PageError"],
|
||||
cachedMessages: ["PageError"],
|
||||
};
|
||||
|
||||
this.sendMessageToTab(aTab, "WebConsole:Init", message);
|
||||
this._updateErrorsCount();
|
||||
};
|
||||
|
||||
@ -319,14 +314,10 @@ DeveloperToolbar.prototype._stopErrorsCount = function DT__stopErrorsCount(aTab)
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendMessageToTab(aTab, "WebConsole:Destroy", {});
|
||||
|
||||
let messageManager = aTab.linkedBrowser.messageManager;
|
||||
this._contentMessageListeners.forEach(function(aName) {
|
||||
messageManager.removeMessageListener(aName, this);
|
||||
}, this);
|
||||
|
||||
this._errorListeners[tabId].destroy();
|
||||
delete this._errorListeners[tabId];
|
||||
delete this._errorsCount[tabId];
|
||||
|
||||
this._updateErrorsCount();
|
||||
};
|
||||
|
||||
@ -434,61 +425,13 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
|
||||
};
|
||||
|
||||
/**
|
||||
* The handler of messages received from the nsIMessageManager.
|
||||
*
|
||||
* @param object aMessage the message received from the content process.
|
||||
*/
|
||||
DeveloperToolbar.prototype.receiveMessage = function DT_receiveMessage(aMessage)
|
||||
{
|
||||
if (!aMessage.json || !(aMessage.json.hudId in this._errorsCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tabId = aMessage.json.hudId;
|
||||
let errors = this._errorsCount[tabId];
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "WebConsole:PageError":
|
||||
this._onPageError(tabId, aMessage.json.pageError);
|
||||
break;
|
||||
case "WebConsole:CachedMessages":
|
||||
aMessage.json.messages.forEach(this._onPageError.bind(this, tabId));
|
||||
break;
|
||||
}
|
||||
|
||||
if (errors != this._errorsCount[tabId]) {
|
||||
this._updateErrorsCount(tabId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a message to the content process using the nsIMessageManager of the
|
||||
* given tab.
|
||||
*
|
||||
* @param nsIDOMNode aTab the tab you want to send a message to.
|
||||
* @param string aName the name of the message you want to send.
|
||||
* @param object aMessage the message to send.
|
||||
*/
|
||||
DeveloperToolbar.prototype.sendMessageToTab =
|
||||
function DT_sendMessageToTab(aTab, aName, aMessage)
|
||||
{
|
||||
let tabId = aTab.linkedPanel;
|
||||
aMessage.hudId = tabId;
|
||||
if (!("id" in aMessage)) {
|
||||
aMessage.id = "DevToolbar-" + this.sequenceId;
|
||||
}
|
||||
|
||||
aTab.linkedBrowser.messageManager.sendAsyncMessage(aName, aMessage);
|
||||
};
|
||||
|
||||
/**
|
||||
* Process a "WebConsole:PageError" message received from the given tab. This
|
||||
* method counts the JavaScript exceptions received.
|
||||
* Count a page error received for the currently selected tab. This
|
||||
* method counts the JavaScript exceptions received and CSS errors/warnings.
|
||||
*
|
||||
* @private
|
||||
* @param string aTabId the ID of the tab from where the page error comes.
|
||||
* @param object aPageError the page error object received from the content
|
||||
* process.
|
||||
* @param object aPageError the page error object received from the
|
||||
* PageErrorListener.
|
||||
*/
|
||||
DeveloperToolbar.prototype._onPageError =
|
||||
function DT__onPageError(aTabId, aPageError)
|
||||
@ -501,6 +444,7 @@ function DT__onPageError(aTabId, aPageError)
|
||||
}
|
||||
|
||||
this._errorsCount[aTabId]++;
|
||||
this._updateErrorsCount(aTabId);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -47,8 +47,11 @@ function test() {
|
||||
|
||||
function addErrors() {
|
||||
expectUncaughtException();
|
||||
let button = content.document.querySelector("button");
|
||||
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
|
||||
|
||||
waitForFocus(function() {
|
||||
let button = content.document.querySelector("button");
|
||||
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
|
||||
}, content);
|
||||
|
||||
waitForValue({
|
||||
name: "button shows one more error after click in page",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -57,9 +57,6 @@ const MINIMUM_PAGE_HEIGHT = 50;
|
||||
// The default console height, as a ratio from the content window inner height.
|
||||
const DEFAULT_CONSOLE_HEIGHT = 0.33;
|
||||
|
||||
// This script is inserted into the content process.
|
||||
const CONTENT_SCRIPT_URL = "chrome://browser/content/devtools/HUDService-content.js";
|
||||
|
||||
// points to the file to load in the Web Console iframe.
|
||||
const UI_IFRAME_URL = "chrome://browser/content/devtools/webconsole.xul";
|
||||
|
||||
@ -500,9 +497,11 @@ HUD_SERVICE.prototype =
|
||||
function WebConsole(aTab)
|
||||
{
|
||||
this.tab = aTab;
|
||||
this.chromeDocument = this.tab.ownerDocument;
|
||||
this.chromeWindow = this.chromeDocument.defaultView;
|
||||
this.hudId = "hud_" + this.tab.linkedPanel;
|
||||
this._onIframeLoad = this._onIframeLoad.bind(this);
|
||||
this._asyncRequests = {};
|
||||
this._init();
|
||||
this._initUI();
|
||||
}
|
||||
|
||||
WebConsole.prototype = {
|
||||
@ -512,6 +511,9 @@ WebConsole.prototype = {
|
||||
*/
|
||||
tab: null,
|
||||
|
||||
chromeWindow: null,
|
||||
chromeDocument: null,
|
||||
|
||||
/**
|
||||
* Getter for HUDService.lastFinishedRequestCallback.
|
||||
*
|
||||
@ -520,15 +522,6 @@ WebConsole.prototype = {
|
||||
*/
|
||||
get lastFinishedRequestCallback() HUDService.lastFinishedRequestCallback,
|
||||
|
||||
/**
|
||||
* Track callback functions registered for specific async requests sent to
|
||||
* the content process.
|
||||
*
|
||||
* @private
|
||||
* @type object
|
||||
*/
|
||||
_asyncRequests: null,
|
||||
|
||||
/**
|
||||
* The xul:panel that holds the Web Console when it is positioned as a window.
|
||||
* @type nsIDOMElement
|
||||
@ -555,22 +548,6 @@ WebConsole.prototype = {
|
||||
|
||||
get gViewSourceUtils() this.chromeWindow.gViewSourceUtils,
|
||||
|
||||
/**
|
||||
* Initialize the Web Console instance.
|
||||
* @private
|
||||
*/
|
||||
_init: function WC__init()
|
||||
{
|
||||
this.chromeDocument = this.tab.ownerDocument;
|
||||
this.chromeWindow = this.chromeDocument.defaultView;
|
||||
this.messageManager = this.tab.linkedBrowser.messageManager;
|
||||
this.hudId = "hud_" + this.tab.linkedPanel;
|
||||
this.notificationBox = this.chromeDocument
|
||||
.getElementById(this.tab.linkedPanel);
|
||||
|
||||
this._initUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the Web Console UI. This method sets up the iframe.
|
||||
* @private
|
||||
@ -783,7 +760,7 @@ WebConsole.prototype = {
|
||||
|
||||
// get the node position index
|
||||
let nodeIdx = this.positions[aPosition];
|
||||
let nBox = this.notificationBox;
|
||||
let nBox = this.chromeDocument.getElementById(this.tab.linkedPanel);
|
||||
let node = nBox.childNodes[nodeIdx];
|
||||
|
||||
// check to see if console is already positioned in aPosition
|
||||
@ -887,92 +864,6 @@ WebConsole.prototype = {
|
||||
this.chromeWindow.DeveloperToolbar.resetErrorsCount(this.tab);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the message manager used to communicate with the Web Console content
|
||||
* script. This method loads the content script, adds the message listeners
|
||||
* and initializes the connection to the content script.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupMessageManager: function WC__setupMessageManager()
|
||||
{
|
||||
this.messageManager.loadFrameScript(CONTENT_SCRIPT_URL, true);
|
||||
|
||||
this._messageListeners.forEach(function(aName) {
|
||||
this.messageManager.addMessageListener(aName, this.ui);
|
||||
}, this);
|
||||
|
||||
let message = {
|
||||
features: ["NetworkMonitor", "LocationChange"],
|
||||
NetworkMonitor: { monitorFileActivity: true },
|
||||
preferences: {
|
||||
"NetworkMonitor.saveRequestAndResponseBodies":
|
||||
this.ui.saveRequestAndResponseBodies,
|
||||
},
|
||||
};
|
||||
|
||||
this.sendMessageToContent("WebConsole:Init", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for messages that have an associated callback function. The
|
||||
* this.sendMessageToContent() allows one to provide a function to be invoked
|
||||
* when the content script replies to the message previously sent. This is the
|
||||
* method that invokes the callback.
|
||||
*
|
||||
* @see this.sendMessageToContent
|
||||
* @private
|
||||
* @param object aResponse
|
||||
* Message object received from the content script.
|
||||
*/
|
||||
_receiveMessageWithCallback:
|
||||
function WC__receiveMessageWithCallback(aResponse)
|
||||
{
|
||||
if (aResponse.id in this._asyncRequests) {
|
||||
let request = this._asyncRequests[aResponse.id];
|
||||
request.callback(aResponse, request.message);
|
||||
delete this._asyncRequests[aResponse.id];
|
||||
}
|
||||
else {
|
||||
Cu.reportError("receiveMessageWithCallback response for stale request " +
|
||||
"ID " + aResponse.id);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a message to the content script.
|
||||
*
|
||||
* @param string aName
|
||||
* The name of the message you want to send.
|
||||
*
|
||||
* @param object aMessage
|
||||
* The message object you want to send. This object needs to have no
|
||||
* cyclic references and it needs to be JSON-stringifiable.
|
||||
*
|
||||
* @param function [aCallback]
|
||||
* Optional function you want to have called when the content script
|
||||
* replies to your message. Your callback receives two arguments:
|
||||
* (1) the response object from the content script and (2) the message
|
||||
* you sent to the content script (which is aMessage here).
|
||||
*/
|
||||
sendMessageToContent:
|
||||
function WC_sendMessageToContent(aName, aMessage, aCallback)
|
||||
{
|
||||
aMessage.hudId = this.hudId;
|
||||
if (!("id" in aMessage)) {
|
||||
aMessage.id = "HUDChrome-" + HUDService.sequenceId();
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
this._asyncRequests[aMessage.id] = {
|
||||
name: aName,
|
||||
message: aMessage,
|
||||
callback: aCallback,
|
||||
};
|
||||
}
|
||||
this.messageManager.sendAsyncMessage(aName, aMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for page location changes. If the Web Console is
|
||||
* opened in a panel the panel title is updated.
|
||||
|
@ -8,7 +8,7 @@ function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
addTab("data:text/html,test for bug 676722 - inspectable objects for window.console");
|
||||
addTab("data:text/html;charset=utf8,test for bug 676722 - inspectable objects for window.console");
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
@ -37,14 +37,14 @@ function test() {
|
||||
|
||||
let uri = Services.io.newFileURI(dir);
|
||||
|
||||
addTab(uri.spec);
|
||||
addTab("data:text/html;charset=utf8,<p>test file URI");
|
||||
browser.addEventListener("load", function tabLoad() {
|
||||
browser.removeEventListener("load", tabLoad, true);
|
||||
openConsole(null, function(aHud) {
|
||||
hud = aHud;
|
||||
hud.jsterm.clearOutput();
|
||||
browser.addEventListener("load", tabReload, true);
|
||||
content.location.reload();
|
||||
content.location = uri.spec;
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ function consoleOpened(aHud) {
|
||||
// __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__
|
||||
// constructor hasOwnProperty isPrototypeOf propertyIsEnumerable
|
||||
// toLocaleString toSource toString unwatch valueOf watch.
|
||||
let props = WCU.namesAndValuesOf(content.wrappedJSObject.document.body);
|
||||
let props = WCU.inspectObject(content.wrappedJSObject.document.body,
|
||||
function() { });
|
||||
is(popup.itemCount, 14 + props.length, "popup.itemCount is correct");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", autocompletePopupHidden, false);
|
||||
|
@ -13,7 +13,7 @@
|
||||
const TEST_HTTPS_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html";
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html,Web Console basic network logging test");
|
||||
addTab("data:text/html;charset=utf8,Web Console mixed content test");
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
}
|
||||
|
||||
@ -68,8 +68,9 @@ function testClickOpenNewTab(warningNode) {
|
||||
let oldOpenUILinkIn = window.openUILinkIn;
|
||||
|
||||
window.openUILinkIn = function(aLink) {
|
||||
if (aLink == "https://developer.mozilla.org/en/Security/MixedContent");
|
||||
linkOpened = true;
|
||||
if (aLink == "https://developer.mozilla.org/en/Security/MixedContent") {
|
||||
linkOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(warningNode, 2, 2, {},
|
||||
|
@ -1,5 +1,6 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Content test - http on https</title>
|
||||
<script src="testscript.js"></script>
|
||||
<!--
|
||||
|
@ -187,6 +187,10 @@ function WebConsoleFrame(aWebConsoleOwner, aPosition)
|
||||
|
||||
this._toggleFilter = this._toggleFilter.bind(this);
|
||||
this._onPositionConsoleCommand = this._onPositionConsoleCommand.bind(this);
|
||||
this._flushMessageQueue = this._flushMessageQueue.bind(this);
|
||||
|
||||
this._outputTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._outputTimerInitialized = false;
|
||||
|
||||
this._initDefaultFilterPrefs();
|
||||
this._commandController = new CommandController(this);
|
||||
@ -194,7 +198,6 @@ function WebConsoleFrame(aWebConsoleOwner, aPosition)
|
||||
|
||||
this.jsterm = new JSTerm(this);
|
||||
this.jsterm.inputNode.focus();
|
||||
|
||||
this._initConnection();
|
||||
}
|
||||
|
||||
@ -264,6 +267,15 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_flushCallback: null,
|
||||
|
||||
/**
|
||||
* Timer used for flushing the messages output queue.
|
||||
*
|
||||
* @private
|
||||
* @type nsITimer
|
||||
*/
|
||||
_outputTimer: null,
|
||||
_outputTimerInitialized: null,
|
||||
|
||||
/**
|
||||
* Store for tracking repeated CSS nodes.
|
||||
* @private
|
||||
@ -1726,10 +1738,8 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
this._outputQueue.push([aCategory, aMethodOrNode, aArguments]);
|
||||
|
||||
if (!this._outputTimeout) {
|
||||
this._outputTimeout =
|
||||
this.window.setTimeout(this._flushMessageQueue.bind(this),
|
||||
OUTPUT_INTERVAL);
|
||||
if (!this._outputTimerInitialized) {
|
||||
this._initOutputTimer();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1742,19 +1752,21 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_flushMessageQueue: function WCF__flushMessageQueue()
|
||||
{
|
||||
if (!this._outputTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let timeSinceFlush = Date.now() - this._lastOutputFlush;
|
||||
if (this._outputQueue.length > MESSAGES_IN_INTERVAL &&
|
||||
timeSinceFlush < THROTTLE_UPDATES) {
|
||||
this._outputTimeout =
|
||||
this.window.setTimeout(this._flushMessageQueue.bind(this),
|
||||
OUTPUT_INTERVAL);
|
||||
this._initOutputTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine how many messages we can display now.
|
||||
let toDisplay = Math.min(this._outputQueue.length, MESSAGES_IN_INTERVAL);
|
||||
if (toDisplay < 1) {
|
||||
this._outputTimeout = null;
|
||||
this._outputTimerInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1767,7 +1779,7 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
let batch = this._outputQueue.splice(0, toDisplay);
|
||||
if (!batch.length) {
|
||||
this._outputTimeout = null;
|
||||
this._outputTimerInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1825,18 +1837,32 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
// If the queue is not empty, schedule another flush.
|
||||
if (this._outputQueue.length > 0) {
|
||||
this._outputTimeout =
|
||||
this.window.setTimeout(this._flushMessageQueue.bind(this),
|
||||
OUTPUT_INTERVAL);
|
||||
this._initOutputTimer();
|
||||
}
|
||||
else {
|
||||
this._outputTimeout = null;
|
||||
this._outputTimerInitialized = false;
|
||||
this._flushCallback && this._flushCallback();
|
||||
}
|
||||
|
||||
this._lastOutputFlush = Date.now();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the output timer.
|
||||
* @private
|
||||
*/
|
||||
_initOutputTimer: function WCF__initOutputTimer()
|
||||
{
|
||||
if (!this._outputTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._outputTimerInitialized = true;
|
||||
this._outputTimer.initWithCallback(this._flushMessageQueue,
|
||||
OUTPUT_INTERVAL,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Output a message from the queue.
|
||||
*
|
||||
@ -2545,7 +2571,9 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_releaseObject: function WCF__releaseObject(aActor)
|
||||
{
|
||||
this.proxy.releaseActor(aActor);
|
||||
if (this.proxy) {
|
||||
this.proxy.releaseActor(aActor);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -2572,13 +2600,28 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
destroy: function WCF_destroy(aOnDestroy)
|
||||
{
|
||||
this._cssNodes = {};
|
||||
this._outputQueue = [];
|
||||
this._pruneCategoriesQueue = {};
|
||||
this._networkRequests = {};
|
||||
|
||||
if (this._outputTimerInitialized) {
|
||||
this._outputTimerInitialized = false;
|
||||
this._outputTimer.cancel();
|
||||
}
|
||||
this._outputTimer = null;
|
||||
|
||||
if (this.proxy) {
|
||||
this.proxy.disconnect(aOnDestroy);
|
||||
this.proxy = null;
|
||||
}
|
||||
|
||||
if (this.jsterm) {
|
||||
this.jsterm.destroy();
|
||||
this.jsterm = null;
|
||||
}
|
||||
|
||||
this._commandController = null;
|
||||
},
|
||||
};
|
||||
|
||||
@ -2675,6 +2718,10 @@ JSTerm.prototype = {
|
||||
_executeResultCallback:
|
||||
function JST__executeResultCallback(aAfterNode, aCallback, aResponse)
|
||||
{
|
||||
if (!this.hud) {
|
||||
return;
|
||||
}
|
||||
|
||||
let errorMessage = aResponse.errorMessage;
|
||||
let result = aResponse.result;
|
||||
let inspectable = result && typeof result == "object" && result.inspectable;
|
||||
@ -3594,10 +3641,13 @@ JSTerm.prototype = {
|
||||
this.clearOutput();
|
||||
|
||||
this.autocompletePopup.destroy();
|
||||
this.autocompletePopup = null;
|
||||
|
||||
this.inputNode.removeEventListener("keypress", this._keyPress, false);
|
||||
this.inputNode.removeEventListener("input", this._inputEventHandler, false);
|
||||
this.inputNode.removeEventListener("keyup", this._inputEventHandler, false);
|
||||
|
||||
this.hud = null;
|
||||
},
|
||||
};
|
||||
|
||||
@ -3837,6 +3887,14 @@ WebConsoleConnectionProxy.prototype = {
|
||||
*/
|
||||
client: null,
|
||||
|
||||
/**
|
||||
* The WebConsoleClient object.
|
||||
*
|
||||
* @see WebConsoleClient
|
||||
* @type object
|
||||
*/
|
||||
webConsoleClient: null,
|
||||
|
||||
/**
|
||||
* Tells if the connection is established.
|
||||
* @type boolean
|
||||
@ -4104,6 +4162,7 @@ WebConsoleConnectionProxy.prototype = {
|
||||
this.client = null;
|
||||
this.webConsoleClient = null;
|
||||
this.connected = false;
|
||||
this.owner = null;
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -44,21 +44,7 @@ const REGEX_MATCH_FUNCTION_NAME = /^\(?function\s+([^(\s]+)\s*\(/;
|
||||
// Match the function arguments from the result of toString() or toSource().
|
||||
const REGEX_MATCH_FUNCTION_ARGS = /^\(?function\s*[^\s(]*\s*\((.+?)\)/;
|
||||
|
||||
const TYPES = { OBJECT: 0,
|
||||
FUNCTION: 1,
|
||||
ARRAY: 2,
|
||||
OTHER: 3,
|
||||
ITERATOR: 4,
|
||||
GETTER: 5,
|
||||
GENERATOR: 6,
|
||||
STRING: 7
|
||||
};
|
||||
|
||||
var gObjectId = 0;
|
||||
|
||||
var WebConsoleUtils = {
|
||||
TYPES: TYPES,
|
||||
|
||||
/**
|
||||
* Convenience function to unwrap a wrapped object.
|
||||
*
|
||||
@ -354,103 +340,6 @@ var WebConsoleUtils = {
|
||||
return type.toLowerCase();
|
||||
},
|
||||
|
||||
/**
|
||||
* Figures out the type of aObject and the string to display as the object
|
||||
* value.
|
||||
*
|
||||
* @see TYPES
|
||||
* @param object aObject
|
||||
* The object to operate on.
|
||||
* @return object
|
||||
* An object of the form:
|
||||
* {
|
||||
* type: TYPES.OBJECT || TYPES.FUNCTION || ...
|
||||
* display: string for displaying the object
|
||||
* }
|
||||
*/
|
||||
presentableValueFor: function WCU_presentableValueFor(aObject)
|
||||
{
|
||||
let type = this.getResultType(aObject);
|
||||
let presentable;
|
||||
|
||||
switch (type) {
|
||||
case "undefined":
|
||||
case "null":
|
||||
return {
|
||||
type: TYPES.OTHER,
|
||||
display: type
|
||||
};
|
||||
|
||||
case "array":
|
||||
return {
|
||||
type: TYPES.ARRAY,
|
||||
display: "Array"
|
||||
};
|
||||
|
||||
case "string":
|
||||
return {
|
||||
type: TYPES.STRING,
|
||||
display: "\"" + aObject + "\""
|
||||
};
|
||||
|
||||
case "date":
|
||||
case "regexp":
|
||||
case "number":
|
||||
case "boolean":
|
||||
return {
|
||||
type: TYPES.OTHER,
|
||||
display: aObject.toString()
|
||||
};
|
||||
|
||||
case "iterator":
|
||||
return {
|
||||
type: TYPES.ITERATOR,
|
||||
display: "Iterator"
|
||||
};
|
||||
|
||||
case "function":
|
||||
presentable = aObject.toString();
|
||||
return {
|
||||
type: TYPES.FUNCTION,
|
||||
display: presentable.substring(0, presentable.indexOf(')') + 1)
|
||||
};
|
||||
|
||||
default:
|
||||
presentable = String(aObject);
|
||||
let m = /^\[object (\S+)\]/.exec(presentable);
|
||||
|
||||
try {
|
||||
if (typeof aObject == "object" && typeof aObject.next == "function" &&
|
||||
m && m[1] == "Generator") {
|
||||
return {
|
||||
type: TYPES.GENERATOR,
|
||||
display: m[1]
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// window.history.next throws in the typeof check above.
|
||||
return {
|
||||
type: TYPES.OBJECT,
|
||||
display: m ? m[1] : "Object"
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof aObject == "object" &&
|
||||
typeof aObject.__iterator__ == "function") {
|
||||
return {
|
||||
type: TYPES.ITERATOR,
|
||||
display: "Iterator"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: TYPES.OBJECT,
|
||||
display: m ? m[1] : "Object"
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells if the given function is native or not.
|
||||
*
|
||||
@ -519,95 +408,6 @@ var WebConsoleUtils = {
|
||||
return desc;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an array that describes the properties of the given object.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object to get the properties from.
|
||||
* @param object aObjectCache
|
||||
* Optional object cache where to store references to properties of
|
||||
* aObject that are inspectable. See this.isObjectInspectable().
|
||||
* @return array
|
||||
* An array that describes each property from the given object. Each
|
||||
* array element is an object (a property descriptor). Each property
|
||||
* descriptor has the following properties:
|
||||
* - name - property name
|
||||
* - value - a presentable property value representation (see
|
||||
* this.presentableValueFor())
|
||||
* - type - value type (see this.presentableValueFor())
|
||||
* - inspectable - tells if the property value holds further
|
||||
* properties (see this.isObjectInspectable()).
|
||||
* - objectId - optional, available only if aObjectCache is given and
|
||||
* if |inspectable| is true. You can do
|
||||
* aObjectCache[propertyDescriptor.objectId] to get the actual object
|
||||
* referenced by the property of aObject.
|
||||
*/
|
||||
namesAndValuesOf: function WCU_namesAndValuesOf(aObject, aObjectCache)
|
||||
{
|
||||
let pairs = [];
|
||||
let value, presentable;
|
||||
|
||||
let isDOMDocument = aObject instanceof Ci.nsIDOMDocument;
|
||||
let deprecated = ["width", "height", "inputEncoding"];
|
||||
|
||||
for (let propName in aObject) {
|
||||
// See bug 632275: skip deprecated properties.
|
||||
if (isDOMDocument && deprecated.indexOf(propName) > -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Also skip non-native getters.
|
||||
if (this.isNonNativeGetter(aObject, propName)) {
|
||||
value = "";
|
||||
presentable = {type: TYPES.GETTER, display: "Getter"};
|
||||
}
|
||||
else {
|
||||
try {
|
||||
value = aObject[propName];
|
||||
presentable = this.presentableValueFor(value);
|
||||
}
|
||||
catch (ex) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let pair = {};
|
||||
pair.name = propName;
|
||||
pair.value = presentable.display;
|
||||
pair.inspectable = false;
|
||||
pair.type = presentable.type;
|
||||
|
||||
switch (presentable.type) {
|
||||
case TYPES.GETTER:
|
||||
case TYPES.ITERATOR:
|
||||
case TYPES.GENERATOR:
|
||||
case TYPES.STRING:
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
for (let p in value) {
|
||||
pair.inspectable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ex) { }
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the inspectable object.
|
||||
if (pair.inspectable && aObjectCache) {
|
||||
pair.objectId = ++gObjectId;
|
||||
aObjectCache[pair.objectId] = value;
|
||||
}
|
||||
|
||||
pairs.push(pair);
|
||||
}
|
||||
|
||||
pairs.sort(this.propertiesSort);
|
||||
|
||||
return pairs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sort function for object properties.
|
||||
*
|
||||
@ -1368,7 +1168,7 @@ function getMatchedProps(aObj, aOptions = {matchProp: ""})
|
||||
aObj = aObj.constructor.prototype;
|
||||
}
|
||||
let c = MAX_COMPLETIONS;
|
||||
let names = {}; // Using an Object to avoid duplicates.
|
||||
let names = Object.create(null); // Using an Object to avoid duplicates.
|
||||
|
||||
// We need to go up the prototype chain.
|
||||
let ownNames = null;
|
||||
@ -1378,7 +1178,7 @@ function getMatchedProps(aObj, aOptions = {matchProp: ""})
|
||||
// Filtering happens here.
|
||||
// If we already have it in, no need to append it.
|
||||
if (ownNames[i].indexOf(aOptions.matchProp) != 0 ||
|
||||
names[ownNames[i]] == true) {
|
||||
ownNames[i] in names) {
|
||||
continue;
|
||||
}
|
||||
c--;
|
||||
|
Loading…
Reference in New Issue
Block a user