gecko-dev/devtools/client/performance-new/initializer.js

168 строки
5.7 KiB
JavaScript

/* 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/. */
// @ts-check
/* exported gInit, gDestroy, loader */
/**
* @typedef {import("./@types/perf").PerfFront} PerfFront
* @typedef {import("./@types/perf").PreferenceFront} PreferenceFront
* @typedef {import("./@types/perf").RecordingStateFromPreferences} RecordingStateFromPreferences
* @typedef {import("./@types/perf").PageContext} PageContext
* @typedef {import("./@types/perf").PanelWindow} PanelWindow
* @typedef {import("./@types/perf").Store} Store
* @typedef {import("./@types/perf").MinimallyTypedGeckoProfile} MinimallyTypedGeckoProfile
*/
"use strict";
{
// Create the browser loader, but take care not to conflict with
// TypeScript. See devtools/client/performance-new/typescript.md and
// the section on "Do not overload require" for more information.
const { BrowserLoader } = ChromeUtils.import(
"resource://devtools/client/shared/browser-loader.js"
);
const browserLoader = BrowserLoader({
baseURI: "resource://devtools/client/performance-new/",
window,
});
/**
* @type {any} - Coerce the current scope into an `any`, and assign the
* loaders to the scope. They can then be used freely below.
*/
const scope = this;
scope.require = browserLoader.require;
scope.loader = browserLoader.loader;
}
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const React = require("devtools/client/shared/vendor/react");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const {
FluentL10n,
} = require("devtools/client/shared/fluent-l10n/fluent-l10n");
const Provider = React.createFactory(
require("devtools/client/shared/vendor/react-redux").Provider
);
const LocalizationProvider = React.createFactory(
FluentReact.LocalizationProvider
);
const DevToolsPanel = React.createFactory(
require("devtools/client/performance-new/components/DevToolsPanel")
);
const ProfilerEventHandling = React.createFactory(
require("devtools/client/performance-new/components/ProfilerEventHandling")
);
const createStore = require("devtools/client/shared/redux/create-store");
const selectors = require("devtools/client/performance-new/store/selectors");
const reducers = require("devtools/client/performance-new/store/reducers");
const actions = require("devtools/client/performance-new/store/actions");
const {
receiveProfile,
createMultiModalGetSymbolTableFn,
} = require("devtools/client/performance-new/browser");
const {
setRecordingPreferences,
presets,
getRecordingPreferences,
} = ChromeUtils.import(
"resource://devtools/client/performance-new/popup/background.jsm.js"
);
/**
* This file initializes the DevTools Panel UI. It is in charge of initializing
* the DevTools specific environment, and then passing those requirements into
* the UI.
*/
/**
* Initialize the panel by creating a redux store, and render the root component.
*
* @param {PerfFront} perfFront - The Perf actor's front. Used to start and stop recordings.
* @param {PageContext} pageContext - The context that the UI is being loaded in under.
* @param {(() => void)?} openAboutProfiling - Optional call to open about:profiling
*/
async function gInit(perfFront, pageContext, openAboutProfiling) {
const store = createStore(reducers);
const supportedFeatures = await perfFront.getSupportedFeatures();
if (!openAboutProfiling) {
openAboutProfiling = () => {
const { openTrustedLink } = require("devtools/client/shared/link");
openTrustedLink("about:profiling", {});
};
}
{
// Expose the store as a global, for testing.
const anyWindow = /** @type {any} */ (window);
const panelWindow = /** @type {PanelWindow} */ (anyWindow);
// The store variable is a `ReduxStore`, not our `Store` type, as defined
// in perf.d.ts. Coerce it into the `Store` type.
const anyStore = /** @type {any} */ (store);
panelWindow.gStore = anyStore;
}
const l10n = new FluentL10n();
await l10n.init(["devtools/client/perftools.ftl"]);
// Do some initialization, especially with privileged things that are part of the
// the browser.
store.dispatch(
actions.initializeStore({
perfFront,
receiveProfile,
recordingPreferences: getRecordingPreferences(
pageContext,
supportedFeatures
),
presets,
supportedFeatures,
openAboutProfiling,
pageContext: "devtools",
// Go ahead and hide the implementation details for the component on how the
// preference information is stored
/**
* @param {RecordingStateFromPreferences} newRecordingPreferences
*/
setRecordingPreferences: newRecordingPreferences =>
setRecordingPreferences(pageContext, newRecordingPreferences),
// Configure the getSymbolTable function for the DevTools workflow.
// See createMultiModalGetSymbolTableFn for more information.
getSymbolTableGetter:
/** @type {(profile: MinimallyTypedGeckoProfile) => GetSymbolTableCallback} */
profile =>
createMultiModalGetSymbolTableFn(
profile,
() => selectors.getObjdirs(store.getState()),
selectors.getPerfFront(store.getState())
),
})
);
ReactDOM.render(
Provider(
{ store },
LocalizationProvider(
{ bundles: l10n.getBundles() },
React.createElement(
React.Fragment,
null,
ProfilerEventHandling(),
DevToolsPanel()
)
)
),
document.querySelector("#root")
);
}
function gDestroy() {
ReactDOM.unmountComponentAtNode(document.querySelector("#root"));
}