Bug 1437512 - Use a MutationObserver for disconnecting.
MozReview-Commit-ID: 6ZDWYG1T6X2
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -246,17 +246,17 @@ var BrowserPageActions = {
iframeNode = document.createElement("iframe");
iframeNode.setAttribute("type", "content");
panelNode.appendChild(iframeNode);
}
let popupSet = document.getElementById("mainPopupSet");
popupSet.appendChild(panelNode);
panelNode.addEventListener("popuphidden", () => {
- PanelMultiView.removePopup(panelNode);
+ panelNode.remove();
}, { once: true });
if (iframeNode) {
panelNode.addEventListener("popupshowing", () => {
action.onIframeShowing(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener("popuphiding", () => {
action.onIframeHiding(iframeNode, panelNode);
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -176,35 +176,16 @@ this.PanelMultiView = class extends this
if (panelMultiViewNode) {
this.forNode(panelMultiViewNode).hidePopup();
} else {
panelNode.hidePopup();
}
}
/**
- * Removes the specified <panel> from the document, ensuring that any
- * <panelmultiview> node it contains is destroyed properly.
- *
- * If the panel does not contain a <panelmultiview>, it is removed directly.
- * This allows consumers like page actions to accept different panel types.
- */
- static removePopup(panelNode) {
- try {
- let panelMultiViewNode = panelNode.querySelector("panelmultiview");
- if (panelMultiViewNode) {
- this.forNode(panelMultiViewNode).disconnect();
- }
- } finally {
- // Make sure to remove the panel element even if disconnecting fails.
- panelNode.remove();
- }
- }
-
- /**
* Ensures that when the specified window is closed all the <panelmultiview>
* node it contains are destroyed properly.
*/
static ensureUnloadHandlerRegistered(window) {
if (gWindowsWithUnloadHandler.has(window)) {
return;
}
@@ -286,16 +267,24 @@ this.PanelMultiView = class extends this
super(node);
this._openPopupPromise = Promise.resolve(false);
this._openPopupCancelCallback = () => {};
}
connect() {
this.connected = true;
+ // This doesn't support moving the node to a different place.
+ this.observer = new this.window.MutationObserver(() => {
+ if (!this._panel.parentNode) {
+ this.disconnect();
+ }
+ });
+ this.observer.observe(this._panel.parentNode, { childList: true });
+
PanelMultiView.ensureUnloadHandlerRegistered(this.window);
let viewContainer = this._viewContainer =
this.document.createElement("box");
viewContainer.classList.add("panel-viewcontainer");
let viewStack = this._viewStack = this.document.createElement("box");
viewStack.classList.add("panel-viewstack");
@@ -350,16 +339,18 @@ this.PanelMultiView = class extends this
});
}
disconnect() {
// Guard against re-entrancy.
if (!this.node || !this.connected)
return;
+ this.observer.disconnect();
+
this._cleanupTransitionPhase();
if (this._ephemeral)
this.hideAllViewsExcept(null);
let mainView = this._mainView;
if (mainView) {
if (this._panelViewCache)
this._panelViewCache.appendChild(mainView);
mainView.removeAttribute("mainview");
@@ -369,17 +360,17 @@ this.PanelMultiView = class extends this
this._panel.removeEventListener("mousemove", this);
this._panel.removeEventListener("popupshowing", this);
this._panel.removeEventListener("popuppositioned", this);
this._panel.removeEventListener("popupshown", this);
this._panel.removeEventListener("popuphidden", this);
this.window.removeEventListener("keydown", this);
this.node = this._openPopupPromise = this._openPopupCancelCallback =
this._viewContainer = this._viewStack = this.__dwu =
- this._panelViewCache = this._transitionDetails = null;
+ this._panelViewCache = this._transitionDetails = this.observer = null;
}
/**
* Tries to open the panel associated with this PanelMultiView, and displays
* the main view specified with the "mainViewId" attribute.
*
* The hidePopup method can be called while the operation is in progress to
* prevent the panel from being displayed. View events may also cancel the
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -438,17 +438,17 @@ const PanelUI = {
let panelRemover = () => {
viewNode.classList.remove("cui-widget-panelview");
if (viewShown) {
CustomizableUI.removePanelCloseListeners(tempPanel);
tempPanel.removeEventListener("popuphidden", panelRemover);
}
aAnchor.open = false;
- PanelMultiView.removePopup(tempPanel);
+ tempPanel.remove();
};
// Wait until all the tasks needed to show a view are done.
PanelMultiView.forNode(multiView).connect();
await multiView.currentShowPromise;
if (!viewShown) {
viewNode.removeEventListener("ViewShown", listener);