Bug 1277834 - Silence inspector warnings and add promise rejection handlers; r=jdescottes
MozReview-Commit-ID: 6NhwdVTH57R
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -86,16 +86,17 @@ function InspectorPanel(iframeWindow, to
this._toolbox = toolbox;
this._target = toolbox._target;
this.panelDoc = iframeWindow.document;
this.panelWin = iframeWindow;
this.panelWin.inspector = this;
this.nodeMenuTriggerInfo = null;
+ this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
this._onBeforeNavigate = this._onBeforeNavigate.bind(this);
this.onNewRoot = this.onNewRoot.bind(this);
this._onContextMenu = this._onContextMenu.bind(this);
this._updateSearchResultsLabel = this._updateSearchResultsLabel.bind(this);
this.onNewSelection = this.onNewSelection.bind(this);
this.onBeforeNewSelection = this.onBeforeNewSelection.bind(this);
this.onDetached = this.onDetached.bind(this);
this.onPaneToggleButtonActivated = this.onPaneToggleButtonActivated.bind(this);
@@ -162,16 +163,28 @@ InspectorPanel.prototype = {
return this._target.client.traits.getUsedFontFaces;
},
get canPasteInnerOrAdjacentHTML() {
return this._target.client.traits.pasteHTML;
},
/**
+ * Handle promise rejections for various asynchronous actions, and only log errors if
+ * the inspector panel still exists.
+ * This is useful to silence useless errors that happen when the inspector is closed
+ * while still initializing (and making protocol requests).
+ */
+ _handleRejectionIfNotDestroyed: function (e) {
+ if (!this._panelDestroyer) {
+ console.error(e);
+ }
+ },
+
+ /**
* Figure out what features the backend supports
*/
_detectActorFeatures: function () {
this._supportsDuplicateNode = false;
this._supportsScrollIntoView = false;
this._supportsResolveRelativeURL = false;
return promise.all([
@@ -253,17 +266,17 @@ InspectorPanel.prototype = {
this._destroyMarkup();
this.isDirty = false;
this._pendingSelection = null;
},
_getPageStyle: function () {
return this._toolbox.inspector.getPageStyle().then(pageStyle => {
this.pageStyle = pageStyle;
- });
+ }, this._handleRejectionIfNotDestroyed);
},
/**
* Return a promise that will resolve to the default node for selection.
*/
_getDefaultNodeForSelection: function () {
if (this._defaultNode) {
return this._defaultNode;
@@ -533,17 +546,18 @@ InspectorPanel.prototype = {
if (!this.markup) {
return;
}
this.markup.expandNode(this.selection.nodeFront);
this.emit("new-root");
});
};
this._pendingSelection = onNodeSelected;
- this._getDefaultNodeForSelection().then(onNodeSelected, console.error);
+ this._getDefaultNodeForSelection()
+ .then(onNodeSelected, this._handleRejectionIfNotDestroyed);
},
_selectionCssSelector: null,
/**
* Set the currently selected node unique css selector.
* Will store the current target url along with it to allow pre-selection at
* reload
@@ -612,26 +626,17 @@ InspectorPanel.prototype = {
}
// On any new selection made by the user, store the unique css selector
// of the selected node so it can be restored after reload of the same page
if (this.canGetUniqueSelector &&
this.selection.isElementNode()) {
selection.getUniqueSelector().then(selector => {
this.selectionCssSelector = selector;
- }).then(null, e => {
- // Only log this as an error if the panel hasn't been destroyed in the
- // meantime.
- if (!this._panelDestroyer) {
- console.error(e);
- } else {
- console.warn("Could not set the unique selector for the newly " +
- "selected node, the inspector was destroyed.");
- }
- });
+ }, this._handleRejectionIfNotDestroyed);
}
let selfUpdate = this.updating("inspector-panel");
executeSoon(() => {
try {
selfUpdate(selection);
} catch (ex) {
console.error(ex);
@@ -1334,17 +1339,17 @@ InspectorPanel.prototype = {
/**
* Clear any pseudo-class locks applied to the current hierarchy.
*/
clearPseudoClasses: function () {
if (!this.walker) {
return promise.resolve();
}
- return this.walker.clearPseudoClassLocks().then(null, console.error);
+ return this.walker.clearPseudoClassLocks().catch(this._handleRejectionIfNotDestroyed);
},
/**
* Edit the outerHTML of the selected Node.
*/
editHTML: function () {
if (!this.selection.isNode()) {
return;
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -114,16 +114,17 @@ function MarkupView(inspector, frame, co
this.popup = new AutocompletePopup(inspector._toolbox, options);
this.undo = new UndoStack();
this.undo.installController(controllerWindow);
this._containers = new Map();
// Binding functions that need to be called in scope.
+ this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
this._mutationObserver = this._mutationObserver.bind(this);
this._onDisplayChange = this._onDisplayChange.bind(this);
this._onMouseClick = this._onMouseClick.bind(this);
this._onMouseUp = this._onMouseUp.bind(this);
this._onNewSelection = this._onNewSelection.bind(this);
this._onCopy = this._onCopy.bind(this);
this._onFocus = this._onFocus.bind(this);
this._onMouseMove = this._onMouseMove.bind(this);
@@ -164,16 +165,28 @@ function MarkupView(inspector, frame, co
MarkupView.prototype = {
/**
* How long does a node flash when it mutates (in ms).
*/
CONTAINER_FLASHING_DURATION: 500,
_selectedContainer: null,
+ /**
+ * Handle promise rejections for various asynchronous actions, and only log errors if
+ * the markup view still exists.
+ * This is useful to silence useless errors that happen when the markup view is
+ * destroyed while still initializing (and making protocol requests).
+ */
+ _handleRejectionIfNotDestroyed: function (e) {
+ if (!this._destroyer) {
+ console.error(e);
+ }
+ },
+
_initTooltips: function () {
this.eventDetailsTooltip = new HTMLTooltip(this._inspector.toolbox,
{type: "arrow"});
this.imagePreviewTooltip = new HTMLTooltip(this._inspector.toolbox,
{type: "arrow", useXulWrapper: "true"});
this._enableImagePreviewTooltip();
},
@@ -586,24 +599,17 @@ MarkupView.prototype = {
}
// Mark the node as selected.
this.markNodeAsSelected(selection.nodeFront);
// Make sure the new selection is navigated to.
this.maybeNavigateToNewSelection();
return undefined;
- }).catch(e => {
- if (!this._destroyer) {
- console.error(e);
- } else {
- console.warn("Could not mark node as selected, the markup-view was " +
- "destroyed while showing the node.");
- }
- });
+ }).catch(this._handleRejectionIfNotDestroyed);
promise.all([onShowBoxModel, onShow]).then(done);
},
/**
* Maybe make selected the current node selection's MarkupContainer depending
* on why the current node got selected.
*/
@@ -1026,18 +1032,18 @@ MarkupView.prototype = {
container.childrenDirty = true;
this._updateChildren(container, {flash: true});
container.update();
}
}
this._waitForChildren().then(() => {
if (this._destroyer) {
- console.warn("Could not fully update after markup mutations, " +
- "the markup-view was destroyed while waiting for children.");
+ // Could not fully update after markup mutations, the markup-view was destroyed
+ // while waiting for children. Bail out silently.
return;
}
this._flashMutatedNodes(mutations);
this._inspector.emit("markupmutation", mutations);
// Since the htmlEditor is absolutely positioned, a mutation may change
// the location in which it should be shown.
this.htmlEditor.refresh();
@@ -1126,36 +1132,27 @@ MarkupView.prototype = {
return this._waitForChildren().then(() => {
if (this._destroyer) {
return promise.reject("markupview destroyed");
}
return this._ensureVisible(node);
}).then(() => {
scrollIntoViewIfNeeded(this.getContainer(node).editor.elt, centered);
- }, e => {
- // Only report this rejection as an error if the panel hasn't been
- // destroyed in the meantime.
- if (!this._destroyer) {
- console.error(e);
- } else {
- console.warn("Could not show the node, the markup-view was destroyed " +
- "while waiting for children");
- }
- });
+ }, this._handleRejectionIfNotDestroyed);
},
/**
* Expand the container's children.
*/
_expandContainer: function (container) {
return this._updateChildren(container, {expand: true}).then(() => {
if (this._destroyer) {
- console.warn("Could not expand the node, the markup-view was " +
- "destroyed");
+ // Could not expand the node, the markup-view was destroyed in the meantime. Just
+ // silently give up.
return;
}
container.setExpanded(true);
});
},
/**
* Expand the node's children.
@@ -1682,17 +1679,17 @@ MarkupView.prototype = {
if (!children.hasLast) {
let span = this.template("more-nodes", data);
fragment.appendChild(span);
}
}
container.children.appendChild(fragment);
return container;
- }).then(null, console.error);
+ }).catch(this._handleRejectionIfNotDestroyed);
this._queuedChildUpdates.set(container, updatePromise);
return updatePromise;
},
_waitForChildren: function () {
if (!this._queuedChildUpdates) {
return promise.resolve(undefined);
}