Bug 1455226 - Load memory/initializer.js via browserRequire instead of a script tag;r=ochameau
"async" methods defined in scripts loaded via a <script> tag seem
to indirectly use the document's Promise, which is not usable after
the DOM of the document has been destroyed.
This is an issue if we invoke this code during the destroy of the
toolbox.
MozReview-Commit-ID: C8juQqJlVDN
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -24,28 +24,26 @@ browser/chrome/browser/skin/classic/brow
browser/chrome/browser/skin/classic/browser/controlcenter/warning-gray.svg
# devtools reduction is bug 1311178
browser/chrome/devtools/content/dom/content/dom-view.css
browser/chrome/devtools/content/dom/dom.html
browser/chrome/devtools/content/dom/main.js
browser/chrome/devtools/content/framework/toolbox-options.js
browser/chrome/devtools/content/inspector/fonts/fonts.js
browser/chrome/devtools/content/inspector/inspector.xhtml
-browser/chrome/devtools/content/memory/initializer.js
browser/chrome/devtools/content/projecteditor/lib/helpers/readdir.js
browser/chrome/devtools/content/shared/theme-switching.js
browser/chrome/devtools/modules/devtools/client/dom/content/dom-view.css
browser/chrome/devtools/modules/devtools/client/dom/dom.html
browser/chrome/devtools/modules/devtools/client/dom/main.js
browser/chrome/devtools/modules/devtools/client/framework/toolbox-options.js
browser/chrome/devtools/modules/devtools/client/inspector/fonts/fonts.js
browser/chrome/devtools/modules/devtools/client/inspector/inspector.xhtml
browser/chrome/devtools/modules/devtools/client/jsonview/css/controls.png
browser/chrome/devtools/modules/devtools/client/jsonview/css/controls@2x.png
-browser/chrome/devtools/modules/devtools/client/memory/initializer.js
browser/chrome/devtools/modules/devtools/client/projecteditor/lib/helpers/readdir.js
browser/chrome/devtools/modules/devtools/client/shared/theme-switching.js
browser/chrome/devtools/modules/devtools/client/themes/common.css
browser/chrome/devtools/modules/devtools/client/themes/toolbars.css
browser/chrome/devtools/modules/devtools/client/themes/variables.css
browser/chrome/devtools/skin/common.css
browser/chrome/devtools/skin/toolbars.css
browser/chrome/devtools/skin/images/command-scratchpad.svg
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -71,17 +71,16 @@ devtools.jar:
content/performance/views/details-abstract-subview.js (performance/views/details-abstract-subview.js)
content/performance/views/details-waterfall.js (performance/views/details-waterfall.js)
content/performance/views/details-js-call-tree.js (performance/views/details-js-call-tree.js)
content/performance/views/details-js-flamegraph.js (performance/views/details-js-flamegraph.js)
content/performance/views/details-memory-call-tree.js (performance/views/details-memory-call-tree.js)
content/performance/views/details-memory-flamegraph.js (performance/views/details-memory-flamegraph.js)
content/performance/views/recordings.js (performance/views/recordings.js)
content/memory/memory.xhtml (memory/memory.xhtml)
- content/memory/initializer.js (memory/initializer.js)
content/commandline/commandlineoutput.xhtml (commandline/commandlineoutput.xhtml)
content/commandline/commandlinetooltip.xhtml (commandline/commandlinetooltip.xhtml)
content/framework/toolbox-window.xul (framework/toolbox-window.xul)
content/framework/toolbox-options.xhtml (framework/toolbox-options.xhtml)
* content/framework/toolbox.xul (framework/toolbox.xul)
content/framework/toolbox-init.js (framework/toolbox-init.js)
content/framework/options-panel.css (framework/options-panel.css)
content/framework/toolbox-process-window.xul (framework/toolbox-process-window.xul)
--- a/devtools/client/memory/initializer.js
+++ b/devtools/client/memory/initializer.js
@@ -1,70 +1,69 @@
/* 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/. */
/* exported initialize, destroy, Promise */
"use strict";
-const BrowserLoaderModule = {};
-ChromeUtils.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
-const { require } = BrowserLoaderModule.BrowserLoader({
- baseURI: "resource://devtools/client/memory/",
- window
-});
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const App = createFactory(require("devtools/client/memory/app"));
const Store = require("devtools/client/memory/store");
const { assert } = require("devtools/shared/DevToolsUtils");
-const Promise = require("Promise");
+
+// Shared variables used by several methods of this module.
+let root, store, unsubscribe;
-/**
- * The current target, toolbox, MemoryFront, and HeapAnalysesClient,
- * set by this tool's host.
- */
-var gToolbox, gFront, gHeapAnalysesClient;
+const initialize = async function() {
+ // Exposed by panel.js
+ let { gFront, gToolbox, gHeapAnalysesClient } = window;
-/**
- * Variables set by `initialize()`
- */
-var gStore, gRoot, gApp, gProvider, unsubscribe, isHighlighted;
+ root = document.querySelector("#app");
+ store = Store();
+ const app = createElement(App, {
+ toolbox: gToolbox,
+ front: gFront,
+ heapWorker: gHeapAnalysesClient
+ });
+ const provider = createElement(Provider, { store }, app);
+ ReactDOM.render(provider, root);
+ unsubscribe = store.subscribe(onStateChange);
-var initialize = async function() {
- gRoot = document.querySelector("#app");
- gStore = Store();
- gApp = createElement(App,
- { toolbox: gToolbox, front: gFront, heapWorker: gHeapAnalysesClient });
- gProvider = createElement(Provider, { store: gStore }, gApp);
- ReactDOM.render(gProvider, gRoot);
- unsubscribe = gStore.subscribe(onStateChange);
+ // Exposed for tests.
+ window.gStore = store;
};
-var destroy = async function() {
- const ok = ReactDOM.unmountComponentAtNode(gRoot);
+const destroy = async function() {
+ const ok = ReactDOM.unmountComponentAtNode(root);
assert(ok, "Should successfully unmount the memory tool's top level React component");
unsubscribe();
+};
- gStore = gRoot = gApp = gProvider = unsubscribe = isHighlighted = null;
-};
+// Current state
+let isHighlighted;
/**
* Fired on any state change, currently only handles toggling
* the highlighting of the tool when recording allocations.
*/
function onStateChange() {
- let isRecording = gStore.getState().allocations.recording;
+ let { gToolbox } = window;
+
+ let isRecording = store.getState().allocations.recording;
if (isRecording === isHighlighted) {
return;
}
if (isRecording) {
gToolbox.highlightTool("memory");
} else {
gToolbox.unhighlightTool("memory");
}
isHighlighted = isRecording;
}
+
+module.exports = { initialize, destroy };
--- a/devtools/client/memory/memory.xhtml
+++ b/devtools/client/memory/memory.xhtml
@@ -20,21 +20,16 @@
<div id="app"></div>
<script type="application/javascript"
src="chrome://devtools/content/shared/theme-switching.js"
defer="true">
</script>
<script type="application/javascript"
- src="initializer.js"
- defer="true">
- </script>
-
- <script type="application/javascript"
src="chrome://devtools/content/shared/vendor/d3.js"
defer="true">
</script>
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/dagre-d3.js"
defer="true">
</script>
--- a/devtools/client/memory/moz.build
+++ b/devtools/client/memory/moz.build
@@ -11,16 +11,17 @@ DIRS += [
'components',
'reducers',
]
DevToolsModules(
'app.js',
'constants.js',
'dominator-tree-lazy-children.js',
+ 'initializer.js',
'models.js',
'panel.js',
'reducers.js',
'store.js',
'utils.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
--- a/devtools/client/memory/panel.js
+++ b/devtools/client/memory/panel.js
@@ -1,22 +1,30 @@
/* 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/. */
"use strict";
const EventEmitter = require("devtools/shared/event-emitter");
const { MemoryFront } = require("devtools/shared/fronts/memory");
+const { Cu } = require("chrome");
const HeapAnalysesClient = require("devtools/shared/heapsnapshot/HeapAnalysesClient");
function MemoryPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;
this._toolbox = toolbox;
+ const { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
+ const browserRequire = BrowserLoader({
+ baseURI: "resource://devtools/client/memory/",
+ window: this.panelWin
+ }).require;
+ this.initializer = browserRequire("devtools/client/memory/initializer");
+
EventEmitter.decorate(this);
}
MemoryPanel.prototype = {
async open() {
if (this._opening) {
return this._opening;
}
@@ -27,17 +35,17 @@ MemoryPanel.prototype = {
const rootForm = await this.target.root;
this.panelWin.gFront = new MemoryFront(this.target.client,
this.target.form,
rootForm);
this.panelWin.gHeapAnalysesClient = new HeapAnalysesClient();
await this.panelWin.gFront.attach();
- this._opening = this.panelWin.initialize().then(() => {
+ this._opening = this.initializer.initialize().then(() => {
this.isReady = true;
this.emit("ready");
return this;
});
return this._opening;
},
@@ -50,17 +58,17 @@ MemoryPanel.prototype = {
async destroy() {
// Make sure this panel is not already destroyed.
if (this._destroyer) {
return this._destroyer;
}
await this.panelWin.gFront.detach();
- this._destroyer = this.panelWin.destroy().then(() => {
+ this._destroyer = this.initializer.destroy().then(() => {
// Destroy front to ensure packet handler is removed from client
this.panelWin.gFront.destroy();
this.panelWin.gHeapAnalysesClient.destroy();
this.panelWin = null;
this._opening = null;
this.isReady = false;
this.emit("destroyed");
});