зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1607801 - Create a TypeScript friendly lazy loading mechanism; r=ochameau
This patch changes the lazy loading mechanism to explicitly create a "lazy" object that can be used to load modules. It makes it so that TypeScript can understand what is going on with the lazy loading. I couldn't find a solution to make the Object.define mechanism work for the global object. I briefly considered using the Object.define() method on the returned "lazy" object, as this could be typed correctly, but I felt magically accessing properties was less clear compared to calling a function that has the side effect of maybe loading a module for the first time. Differential Revision: https://phabricator.services.mozilla.com/D59208
This commit is contained in:
Родитель
02e0ad2908
Коммит
46fc6e8cf6
|
@ -45,6 +45,8 @@ declare namespace MockedExports {
|
|||
"resource://devtools/client/shared/browser-loader.js": any;
|
||||
"resource://devtools/client/performance-new/popup/menu-button.jsm.js":
|
||||
typeof import("devtools/client/performance-new/popup/menu-button.jsm.js");
|
||||
"resource://devtools/client/performance-new/typescript-lazy-load.jsm.js":
|
||||
typeof import("devtools/client/performance-new/typescript-lazy-load.jsm.js");
|
||||
"resource://devtools/client/performance-new/popup/panel.jsm.js":
|
||||
typeof import("devtools/client/performance-new/popup/panel.jsm.js");
|
||||
"resource:///modules/PanelMultiView.jsm":
|
||||
|
@ -65,6 +67,7 @@ declare namespace MockedExports {
|
|||
createObjectIn: (content: ContentWindow) => object;
|
||||
exportFunction: (fn: Function, scope: object, options?: object) => void;
|
||||
cloneInto: (value: any, scope: object, options?: object) => void;
|
||||
defineModuleGetter: (target: any, variable: string, path: string) => void;
|
||||
}
|
||||
|
||||
interface MessageManager {
|
||||
|
@ -283,6 +286,10 @@ declare module "chrome" {
|
|||
export = MockedExports.chrome;
|
||||
}
|
||||
|
||||
declare module "ChromeUtils" {
|
||||
export = ChromeUtils;
|
||||
}
|
||||
|
||||
declare module "resource://gre/modules/osfile.jsm" {
|
||||
export = MockedExports.osfileJSM;
|
||||
}
|
||||
|
|
|
@ -20,37 +20,18 @@
|
|||
* @typedef {import("./@types/perf").MinimallyTypedGeckoProfile} MinimallyTypedGeckoProfile
|
||||
*/
|
||||
|
||||
/**
|
||||
* TS-TODO
|
||||
*
|
||||
* This function replaces lazyRequireGetter, and TypeScript can understand it. It's
|
||||
* currently duplicated until we have consensus that TypeScript is a good idea.
|
||||
*
|
||||
* @template T
|
||||
* @type {(callback: () => T) => () => T}
|
||||
*/
|
||||
function requireLazy(callback) {
|
||||
/** @type {T | undefined} */
|
||||
let cache;
|
||||
return () => {
|
||||
if (cache === undefined) {
|
||||
cache = callback();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
}
|
||||
|
||||
const lazyServices = requireLazy(() =>
|
||||
require("resource://gre/modules/Services.jsm")
|
||||
const ChromeUtils = require("ChromeUtils");
|
||||
const { createLazyLoaders } = ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/typescript-lazy-load.jsm.js"
|
||||
);
|
||||
|
||||
const lazyChrome = requireLazy(() => require("chrome"));
|
||||
|
||||
const lazyOS = requireLazy(() => require("resource://gre/modules/osfile.jsm"));
|
||||
|
||||
const lazyProfilerGetSymbols = requireLazy(() =>
|
||||
require("resource://gre/modules/ProfilerGetSymbols.jsm")
|
||||
);
|
||||
const lazy = createLazyLoaders({
|
||||
Chrome: () => require("chrome"),
|
||||
Services: () => require("Services"),
|
||||
OS: () => ChromeUtils.import("resource://gre/modules/osfile.jsm"),
|
||||
ProfilerGetSymbols: () =>
|
||||
ChromeUtils.import("resource://gre/modules/ProfilerGetSymbols.jsm"),
|
||||
});
|
||||
|
||||
const TRANSFER_EVENT = "devtools:perf-html-transfer-profile";
|
||||
const SYMBOL_TABLE_REQUEST_EVENT = "devtools:perf-html-request-symbol-table";
|
||||
|
@ -84,7 +65,7 @@ const UI_BASE_URL_PATH_DEFAULT = "/from-addon";
|
|||
* returned promise with it.
|
||||
*/
|
||||
function receiveProfile(profile, getSymbolTableCallback) {
|
||||
const { Services } = lazyServices();
|
||||
const Services = lazy.Services();
|
||||
// Find the most recently used window, as the DevTools client could be in a variety
|
||||
// of hosts.
|
||||
const win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
|
@ -221,7 +202,7 @@ async function getSymbolTableFromDebuggee(perfFront, path, breakpadId) {
|
|||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function doesFileExistAtPath(path) {
|
||||
const { OS } = lazyOS();
|
||||
const { OS } = lazy.OS();
|
||||
try {
|
||||
const result = await OS.File.stat(path);
|
||||
return !result.isDir;
|
||||
|
@ -254,7 +235,7 @@ async function doesFileExistAtPath(path) {
|
|||
* promise is rejected) if nothing was found.
|
||||
*/
|
||||
async function getSymbolTableFromLocalBinary(objdirs, filename, breakpadId) {
|
||||
const { OS } = lazyOS();
|
||||
const { OS } = lazy.OS();
|
||||
const candidatePaths = [];
|
||||
for (const objdirPath of objdirs) {
|
||||
// Binaries are usually expected to exist at objdir/dist/bin/filename.
|
||||
|
@ -268,7 +249,7 @@ async function getSymbolTableFromLocalBinary(objdirs, filename, breakpadId) {
|
|||
|
||||
for (const path of candidatePaths) {
|
||||
if (await doesFileExistAtPath(path)) {
|
||||
const { ProfilerGetSymbols } = lazyProfilerGetSymbols();
|
||||
const { ProfilerGetSymbols } = lazy.ProfilerGetSymbols();
|
||||
try {
|
||||
return await ProfilerGetSymbols.getSymbolTable(path, path, breakpadId);
|
||||
} catch (e) {
|
||||
|
@ -312,7 +293,7 @@ function createMultiModalGetSymbolTableFn(profile, getObjdirs, perfFront) {
|
|||
}
|
||||
const { name, path, debugPath } = result;
|
||||
if (await doesFileExistAtPath(path)) {
|
||||
const { ProfilerGetSymbols } = lazyProfilerGetSymbols();
|
||||
const { ProfilerGetSymbols } = lazy.ProfilerGetSymbols();
|
||||
// This profile was obtained from this machine, and not from a
|
||||
// different device (e.g. an Android phone). Dump symbols from the file
|
||||
// on this machine directly.
|
||||
|
@ -355,8 +336,8 @@ function createMultiModalGetSymbolTableFn(profile, getObjdirs, perfFront) {
|
|||
* @type {RestartBrowserWithEnvironmentVariable}
|
||||
*/
|
||||
function restartBrowserWithEnvironmentVariable(envName, value) {
|
||||
const { Services } = lazyServices();
|
||||
const { Cc, Ci } = lazyChrome();
|
||||
const Services = lazy.Services();
|
||||
const { Cc, Ci } = lazy.Chrome();
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||
Ci.nsIEnvironment
|
||||
);
|
||||
|
@ -373,7 +354,7 @@ function restartBrowserWithEnvironmentVariable(envName, value) {
|
|||
* @type {GetEnvironmentVariable}
|
||||
*/
|
||||
function getEnvironmentVariable(envName) {
|
||||
const { Cc, Ci } = lazyChrome();
|
||||
const { Cc, Ci } = lazy.Chrome();
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||
Ci.nsIEnvironment
|
||||
);
|
||||
|
@ -386,7 +367,7 @@ function getEnvironmentVariable(envName) {
|
|||
* @param {(objdirs: string[]) => unknown} changeObjdirs
|
||||
*/
|
||||
function openFilePickerForObjdir(window, objdirs, changeObjdirs) {
|
||||
const { Cc, Ci } = lazyChrome();
|
||||
const { Cc, Ci } = lazy.Chrome();
|
||||
const FilePicker = Cc["@mozilla.org/filepicker;1"].createInstance(
|
||||
Ci.nsIFilePicker
|
||||
);
|
||||
|
|
|
@ -15,6 +15,7 @@ DevToolsModules(
|
|||
'initializer.js',
|
||||
'panel.js',
|
||||
'preference-management.js',
|
||||
'typescript-lazy-load.jsm.js',
|
||||
'utils.js',
|
||||
)
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
// The following are not lazily loaded as they are needed during initialization.
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { createLazyLoaders } = ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/typescript-lazy-load.jsm.js"
|
||||
);
|
||||
// For some reason TypeScript was giving me an error when de-structuring AppConstants. I
|
||||
// suspect a bug in TypeScript was at play.
|
||||
const AppConstants = ChromeUtils.import(
|
||||
|
@ -48,82 +51,34 @@ const PRESET_PREF = "devtools.performance.recording.preset";
|
|||
/** @type {PerformancePref["PopupFeatureFlag"]} */
|
||||
const POPUP_FEATURE_FLAG_PREF = "devtools.performance.popup.feature-flag";
|
||||
|
||||
// Lazily load the require function, when it's needed.
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"require",
|
||||
"resource://devtools/shared/Loader.jsm"
|
||||
);
|
||||
|
||||
// The following utilities are lazily loaded as they are not needed when controlling the
|
||||
// global state of the profiler, and only are used during specific funcationality like
|
||||
// symbolication or capturing a profile.
|
||||
|
||||
/**
|
||||
* TS-TODO
|
||||
*
|
||||
* This function replaces lazyRequireGetter, and TypeScript can understand it. It's
|
||||
* currently duplicated until we have consensus that TypeScript is a good idea.
|
||||
*
|
||||
* @template T
|
||||
* @type {(callback: () => T) => () => T}
|
||||
*/
|
||||
function requireLazy(callback) {
|
||||
/** @type {T | undefined} */
|
||||
let cache;
|
||||
return () => {
|
||||
if (cache === undefined) {
|
||||
cache = callback();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
}
|
||||
|
||||
const lazyOS = requireLazy(() =>
|
||||
ChromeUtils.import("resource://gre/modules/osfile.jsm")
|
||||
);
|
||||
|
||||
const lazyProfilerGetSymbols = requireLazy(() =>
|
||||
ChromeUtils.import("resource://gre/modules/ProfilerGetSymbols.jsm")
|
||||
);
|
||||
|
||||
const lazyBrowserModule = requireLazy(() => {
|
||||
const { require } = ChromeUtils.import(
|
||||
"resource://devtools/shared/Loader.jsm"
|
||||
);
|
||||
const browserModule = require("devtools/client/performance-new/browser");
|
||||
return browserModule;
|
||||
const lazy = createLazyLoaders({
|
||||
OS: () => ChromeUtils.import("resource://gre/modules/osfile.jsm"),
|
||||
Utils: () => require("devtools/client/performance-new/utils"),
|
||||
BrowserModule: () => require("devtools/client/performance-new/browser"),
|
||||
RecordingUtils: () =>
|
||||
require("devtools/shared/performance-new/recording-utils"),
|
||||
CustomizableUI: () =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableUI.jsm"),
|
||||
PreferenceManagement: () =>
|
||||
require("devtools/client/performance-new/preference-management"),
|
||||
ProfilerGetSymbols: () =>
|
||||
ChromeUtils.import("resource://gre/modules/ProfilerGetSymbols.jsm"),
|
||||
ProfilerMenuButton: () =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/menu-button.jsm.js"
|
||||
),
|
||||
});
|
||||
|
||||
const lazyPreferenceManagement = requireLazy(() => {
|
||||
const { require } = ChromeUtils.import(
|
||||
"resource://devtools/shared/Loader.jsm"
|
||||
);
|
||||
|
||||
const preferenceManagementModule = require("devtools/client/performance-new/preference-management");
|
||||
return preferenceManagementModule;
|
||||
});
|
||||
|
||||
const lazyRecordingUtils = requireLazy(() => {
|
||||
const { require } = ChromeUtils.import(
|
||||
"resource://devtools/shared/Loader.jsm"
|
||||
);
|
||||
|
||||
const recordingUtils = require("devtools/shared/performance-new/recording-utils");
|
||||
return recordingUtils;
|
||||
});
|
||||
|
||||
const lazyUtils = requireLazy(() => {
|
||||
const { require } = ChromeUtils.import(
|
||||
"resource://devtools/shared/Loader.jsm"
|
||||
);
|
||||
const recordingUtils = require("devtools/client/performance-new/utils");
|
||||
return recordingUtils;
|
||||
});
|
||||
|
||||
const lazyProfilerMenuButton = requireLazy(() =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/menu-button.jsm.js"
|
||||
)
|
||||
);
|
||||
|
||||
const lazyCustomizableUI = requireLazy(() =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableUI.jsm")
|
||||
);
|
||||
|
||||
/** @type {Presets} */
|
||||
const presets = {
|
||||
"web-developer": {
|
||||
|
@ -210,7 +165,7 @@ async function getSymbolsFromThisBrowser(debugName, breakpadId) {
|
|||
}
|
||||
|
||||
const { path, debugPath } = cachedLibInfo;
|
||||
const { OS } = lazyOS();
|
||||
const { OS } = lazy.OS();
|
||||
if (!OS.Path.split(path).absolute) {
|
||||
throw new Error(
|
||||
"Services.profiler.sharedLibraries did not contain an absolute path for " +
|
||||
|
@ -219,7 +174,7 @@ async function getSymbolsFromThisBrowser(debugName, breakpadId) {
|
|||
);
|
||||
}
|
||||
|
||||
const { ProfilerGetSymbols } = lazyProfilerGetSymbols();
|
||||
const { ProfilerGetSymbols } = lazy.ProfilerGetSymbols();
|
||||
|
||||
return ProfilerGetSymbols.getSymbolTable(path, debugPath, breakpadId);
|
||||
}
|
||||
|
@ -247,7 +202,7 @@ async function captureProfile() {
|
|||
}
|
||||
);
|
||||
|
||||
const receiveProfile = lazyBrowserModule().receiveProfile;
|
||||
const receiveProfile = lazy.BrowserModule().receiveProfile;
|
||||
receiveProfile(profile, getSymbolsFromThisBrowser);
|
||||
|
||||
Services.profiler.StopProfiler();
|
||||
|
@ -259,7 +214,7 @@ async function captureProfile() {
|
|||
* @param {PageContext} pageContext
|
||||
*/
|
||||
function startProfiler(pageContext) {
|
||||
const { translatePreferencesToState } = lazyPreferenceManagement();
|
||||
const { translatePreferencesToState } = lazy.PreferenceManagement();
|
||||
const {
|
||||
entries,
|
||||
interval,
|
||||
|
@ -271,7 +226,7 @@ function startProfiler(pageContext) {
|
|||
);
|
||||
|
||||
// Get the active BrowsingContext ID from browser.
|
||||
const { getActiveBrowsingContextID } = lazyRecordingUtils();
|
||||
const { getActiveBrowsingContextID } = lazy.RecordingUtils();
|
||||
const activeBrowsingContextID = getActiveBrowsingContextID();
|
||||
|
||||
Services.profiler.StartProfiler(
|
||||
|
@ -352,7 +307,7 @@ function getPrefPostfix(pageContext) {
|
|||
case "aboutprofiling-remote":
|
||||
return ".remote";
|
||||
default: {
|
||||
const { UnhandledCaseError } = lazyUtils();
|
||||
const { UnhandledCaseError } = lazy.Utils();
|
||||
throw new UnhandledCaseError(pageContext, "Page Context");
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +481,7 @@ function handleWebChannelMessage(channel, id, message, target) {
|
|||
case "STATUS_QUERY": {
|
||||
// The content page wants to know if this channel exists. It does, so respond
|
||||
// back to the ping.
|
||||
const { ProfilerMenuButton } = lazyProfilerMenuButton();
|
||||
const { ProfilerMenuButton } = lazy.ProfilerMenuButton();
|
||||
channel.send(
|
||||
{
|
||||
type: "STATUS_RESPONSE",
|
||||
|
@ -549,12 +504,12 @@ function handleWebChannelMessage(channel, id, message, target) {
|
|||
Services.prefs.setBoolPref(POPUP_FEATURE_FLAG_PREF, true);
|
||||
|
||||
// Enable the profiler menu button.
|
||||
const { ProfilerMenuButton } = lazyProfilerMenuButton();
|
||||
const { ProfilerMenuButton } = lazy.ProfilerMenuButton();
|
||||
ProfilerMenuButton.addToNavbar(ownerDocument);
|
||||
|
||||
// Dispatch the change event manually, so that the shortcuts will also be
|
||||
// added.
|
||||
const { CustomizableUI } = lazyCustomizableUI();
|
||||
const { CustomizableUI } = lazy.CustomizableUI();
|
||||
CustomizableUI.dispatchToolboxEvent("customizationchange");
|
||||
|
||||
// Open the popup with a message.
|
||||
|
|
|
@ -4,53 +4,30 @@
|
|||
// @ts-check
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @typedef {import("../@types/perf").PerformancePref} PerformancePref
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file controls the enabling and disabling of the menu button for the profiler.
|
||||
* Care should be taken to keep it minimal as it can be run with browser initialization.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TS-TODO
|
||||
*
|
||||
* This function replaces lazyRequireGetter, and TypeScript can understand it. It's
|
||||
* currently duplicated until we have consensus that TypeScript is a good idea.
|
||||
*
|
||||
* @template T
|
||||
* @type {(callback: () => T) => () => T}
|
||||
*/
|
||||
function requireLazy(callback) {
|
||||
/** @type {T | undefined} */
|
||||
let cache;
|
||||
return () => {
|
||||
if (cache === undefined) {
|
||||
cache = callback();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
}
|
||||
|
||||
// Provide an exports object for the JSM to be properly read by TypeScript.
|
||||
/** @type {any} */ (this).exports = {};
|
||||
|
||||
const lazyServices = requireLazy(() =>
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm")
|
||||
);
|
||||
const lazyCustomizableUI = requireLazy(() =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableUI.jsm")
|
||||
);
|
||||
const lazyCustomizableWidgets = requireLazy(() =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableWidgets.jsm")
|
||||
);
|
||||
const lazyPopupPanel = requireLazy(() =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/panel.jsm.js"
|
||||
)
|
||||
const { createLazyLoaders } = ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/typescript-lazy-load.jsm.js"
|
||||
);
|
||||
|
||||
const lazy = createLazyLoaders({
|
||||
Services: () => ChromeUtils.import("resource://gre/modules/Services.jsm"),
|
||||
CustomizableUI: () =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableUI.jsm"),
|
||||
CustomizableWidgets: () =>
|
||||
ChromeUtils.import("resource:///modules/CustomizableWidgets.jsm"),
|
||||
PopupPanel: () =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/panel.jsm.js"
|
||||
),
|
||||
});
|
||||
|
||||
const WIDGET_ID = "profiler-button";
|
||||
|
||||
/**
|
||||
|
@ -60,7 +37,7 @@ const WIDGET_ID = "profiler-button";
|
|||
* @return {void}
|
||||
*/
|
||||
function addToNavbar(document) {
|
||||
const { CustomizableUI } = lazyCustomizableUI();
|
||||
const { CustomizableUI } = lazy.CustomizableUI();
|
||||
|
||||
CustomizableUI.addWidgetToArea(WIDGET_ID, CustomizableUI.AREA_NAVBAR);
|
||||
}
|
||||
|
@ -72,7 +49,7 @@ function addToNavbar(document) {
|
|||
* @return {void}
|
||||
*/
|
||||
function remove() {
|
||||
const { CustomizableUI } = lazyCustomizableUI();
|
||||
const { CustomizableUI } = lazy.CustomizableUI();
|
||||
CustomizableUI.removeWidgetFromArea(WIDGET_ID);
|
||||
}
|
||||
|
||||
|
@ -83,7 +60,7 @@ function remove() {
|
|||
* @return {boolean}
|
||||
*/
|
||||
function isInNavbar() {
|
||||
const { CustomizableUI } = lazyCustomizableUI();
|
||||
const { CustomizableUI } = lazy.CustomizableUI();
|
||||
return Boolean(CustomizableUI.getPlacementOfWidget("profiler-button"));
|
||||
}
|
||||
|
||||
|
@ -108,9 +85,9 @@ function openPopup(document) {
|
|||
* @return {void}
|
||||
*/
|
||||
function initialize(toggleProfilerKeyShortcuts) {
|
||||
const { CustomizableUI } = lazyCustomizableUI();
|
||||
const { CustomizableWidgets } = lazyCustomizableWidgets();
|
||||
const { Services } = lazyServices();
|
||||
const { CustomizableUI } = lazy.CustomizableUI();
|
||||
const { CustomizableWidgets } = lazy.CustomizableWidgets();
|
||||
const { Services } = lazy.Services();
|
||||
|
||||
const widget = CustomizableUI.getWidget(WIDGET_ID);
|
||||
if (widget && widget.provider == CustomizableUI.PROVIDER_API) {
|
||||
|
@ -143,7 +120,7 @@ function initialize(toggleProfilerKeyShortcuts) {
|
|||
if (!isEnabled) {
|
||||
// The profiler menu button is no longer in the navbar, make sure that the
|
||||
// "intro-displayed" preference is reset.
|
||||
/** @type {PerformancePref["PopupIntroDisplayed"]} */
|
||||
/** @type {import("../@types/perf").PerformancePref["PopupIntroDisplayed"]} */
|
||||
const popupIntroDisplayedPref =
|
||||
"devtools.performance.popup.intro-displayed";
|
||||
Services.prefs.setBoolPref(popupIntroDisplayedPref, false);
|
||||
|
@ -179,7 +156,7 @@ function initialize(toggleProfilerKeyShortcuts) {
|
|||
createViewControllers,
|
||||
addPopupEventHandlers,
|
||||
initializePopup,
|
||||
} = lazyPopupPanel();
|
||||
} = lazy.PopupPanel();
|
||||
|
||||
const panelElements = selectElementsInPanelview(event.target);
|
||||
const panelView = createViewControllers(panelState, panelElements);
|
||||
|
@ -209,7 +186,7 @@ function initialize(toggleProfilerKeyShortcuts) {
|
|||
* @type {(document: HTMLDocument) => void}
|
||||
*/
|
||||
onBeforeCreated: document => {
|
||||
/** @type {PerformancePref["PopupIntroDisplayed"]} */
|
||||
/** @type {import("../@types/perf").PerformancePref["PopupIntroDisplayed"]} */
|
||||
const popupIntroDisplayedPref =
|
||||
"devtools.performance.popup.intro-displayed";
|
||||
|
||||
|
|
|
@ -19,40 +19,19 @@
|
|||
* @property {boolean} isInfoCollapsed
|
||||
*/
|
||||
|
||||
/**
|
||||
* TS-TODO
|
||||
*
|
||||
* This function replaces lazyRequireGetter, and TypeScript can understand it. It's
|
||||
* currently duplicated until we have consensus that TypeScript is a good idea.
|
||||
*
|
||||
* @template T
|
||||
* @type {(callback: () => T) => () => T}
|
||||
*/
|
||||
function requireLazy(callback) {
|
||||
/** @type {T | undefined} */
|
||||
let cache;
|
||||
return () => {
|
||||
if (cache === undefined) {
|
||||
cache = callback();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
}
|
||||
const { createLazyLoaders } = ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/typescript-lazy-load.jsm.js"
|
||||
);
|
||||
|
||||
// Provide an exports object for the JSM to be properly read by TypeScript.
|
||||
/** @type {any} */ (this).module = {};
|
||||
|
||||
const lazyServices = requireLazy(() =>
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm")
|
||||
);
|
||||
const lazyPanelMultiView = requireLazy(() =>
|
||||
ChromeUtils.import("resource:///modules/PanelMultiView.jsm")
|
||||
);
|
||||
const lazyBackground = requireLazy(() =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/background.jsm.js"
|
||||
)
|
||||
);
|
||||
const lazy = createLazyLoaders({
|
||||
Services: () => ChromeUtils.import("resource://gre/modules/Services.jsm"),
|
||||
PanelMultiView: () =>
|
||||
ChromeUtils.import("resource:///modules/PanelMultiView.jsm"),
|
||||
Background: () =>
|
||||
ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/background.jsm.js"
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* This function collects all of the selection of the elements inside of the panel.
|
||||
|
@ -127,8 +106,8 @@ function createViewControllers(state, elements) {
|
|||
},
|
||||
|
||||
updatePresets() {
|
||||
const { Services } = lazyServices();
|
||||
const { presets, getRecordingPreferences } = lazyBackground();
|
||||
const { Services } = lazy.Services();
|
||||
const { presets, getRecordingPreferences } = lazy.Background();
|
||||
const { presetName } = getRecordingPreferences(
|
||||
"aboutprofiling",
|
||||
Services.profiler.GetFeatures()
|
||||
|
@ -143,13 +122,13 @@ function createViewControllers(state, elements) {
|
|||
elements.presetDescription.style.display = "none";
|
||||
elements.presetCustom.style.display = "block";
|
||||
}
|
||||
const { PanelMultiView } = lazyPanelMultiView();
|
||||
const { PanelMultiView } = lazy.PanelMultiView();
|
||||
// Update the description height sizing.
|
||||
PanelMultiView.forNode(elements.panelview).descriptionHeightWorkaround();
|
||||
},
|
||||
|
||||
updateProfilerActive() {
|
||||
const { Services } = lazyServices();
|
||||
const { Services } = lazy.Services();
|
||||
const isProfilerActive = Services.profiler.IsActive();
|
||||
elements.inactive.setAttribute(
|
||||
"hidden",
|
||||
|
@ -170,8 +149,8 @@ function createViewControllers(state, elements) {
|
|||
// The presets were already built.
|
||||
return;
|
||||
}
|
||||
const { Services } = lazyServices();
|
||||
const { presets } = lazyBackground();
|
||||
const { Services } = lazy.Services();
|
||||
const { presets } = lazy.Background();
|
||||
const currentPreset = Services.prefs.getCharPref(
|
||||
"devtools.performance.recording.preset"
|
||||
);
|
||||
|
@ -230,7 +209,7 @@ function initializePopup(state, elements, view) {
|
|||
|
||||
// XUL <description> elements don't vertically size correctly, this is
|
||||
// the workaround for it.
|
||||
const { PanelMultiView } = lazyPanelMultiView();
|
||||
const { PanelMultiView } = lazy.PanelMultiView();
|
||||
PanelMultiView.forNode(elements.panelview).descriptionHeightWorkaround();
|
||||
|
||||
// Now wait for another rAF, and turn the animations back on.
|
||||
|
@ -255,7 +234,7 @@ function addPopupEventHandlers(state, elements, view) {
|
|||
startProfiler,
|
||||
stopProfiler,
|
||||
captureProfile,
|
||||
} = lazyBackground();
|
||||
} = lazy.Background();
|
||||
|
||||
/**
|
||||
* Adds a handler that automatically is removed once the panel is hidden.
|
||||
|
@ -326,7 +305,7 @@ function addPopupEventHandlers(state, elements, view) {
|
|||
});
|
||||
|
||||
// Update the view when the profiler starts/stops.
|
||||
const { Services } = lazyServices();
|
||||
const { Services } = lazy.Services();
|
||||
Services.obs.addObserver(view.updateProfilerActive, "profiler-started");
|
||||
Services.obs.addObserver(view.updateProfilerActive, "profiler-stopped");
|
||||
state.cleanup.push(() => {
|
||||
|
@ -335,6 +314,9 @@ function addPopupEventHandlers(state, elements, view) {
|
|||
});
|
||||
}
|
||||
|
||||
// Provide an exports object for the JSM to be properly read by TypeScript.
|
||||
/** @type {any} */ (this).module = {};
|
||||
|
||||
module.exports = {
|
||||
selectElementsInPanelview,
|
||||
createViewControllers,
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* 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
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* TypeScript can't understand the lazyRequireGetter mechanism, due to how it defines
|
||||
* properties as a getter. This function, instead provides lazy loading in a
|
||||
* TypeScript-friendly manner. It applies the lazy load memoization to each property
|
||||
* of the provided object.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* const lazy = createLazyLoaders({
|
||||
* moduleA: () => require("module/a"),
|
||||
* moduleB: () => require("module/b"),
|
||||
* });
|
||||
*
|
||||
* Later:
|
||||
*
|
||||
* const moduleA = lazy.moduleA();
|
||||
* const { objectInModuleB } = lazy.moduleB();
|
||||
*
|
||||
* @template T
|
||||
* @param {T} definition - An object where each property has a function that loads a module.
|
||||
* @returns {T} - The load memoized version of T.
|
||||
*/
|
||||
function createLazyLoaders(definition) {
|
||||
/** @type {any} */
|
||||
const result = {};
|
||||
for (const [key, callback] of Object.entries(definition)) {
|
||||
/** @type {any} */
|
||||
let cache;
|
||||
result[key] = () => {
|
||||
if (cache === undefined) {
|
||||
cache = callback();
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Provide an exports object for the JSM to be properly read by TypeScript.
|
||||
/** @type {any} */ (this).module = {};
|
||||
|
||||
module.exports = {
|
||||
createLazyLoaders,
|
||||
};
|
||||
|
||||
// Object.keys() confuses the linting which expects a static array expression.
|
||||
// eslint-disable-next-line
|
||||
var EXPORTED_SYMBOLS = Object.keys(module.exports);
|
Загрузка…
Ссылка в новой задаче