@memlab/cli 1.0.6 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/{memlab → memlab.js} +9 -2
- package/dist/BaseCommand.d.ts +1 -1
- package/dist/BaseCommand.js +1 -1
- package/dist/CommandLoader.d.ts +8 -7
- package/dist/CommandLoader.js +8 -1
- package/dist/Dispatcher.d.ts +8 -3
- package/dist/Dispatcher.js +13 -6
- package/dist/TypesThirdParty.d.ts +1 -1
- package/dist/TypesThirdParty.js +1 -1
- package/dist/commands/CleanLoggerDataCommand.d.ts +1 -1
- package/dist/commands/CleanLoggerDataCommand.js +1 -1
- package/dist/commands/CleanRunDataCommand.d.ts +1 -1
- package/dist/commands/CleanRunDataCommand.js +1 -1
- package/dist/commands/GetVersionCommand.d.ts +2 -1
- package/dist/commands/GetVersionCommand.js +21 -2
- package/dist/commands/InitDirectoryCommand.d.ts +1 -1
- package/dist/commands/InitDirectoryCommand.js +1 -1
- package/dist/commands/ListScenariosCommand.d.ts +1 -1
- package/dist/commands/ListScenariosCommand.js +1 -1
- package/dist/commands/MemLabRunCommand.d.ts +1 -1
- package/dist/commands/MemLabRunCommand.js +1 -1
- package/dist/commands/PrintSummaryCommand.d.ts +1 -1
- package/dist/commands/PrintSummaryCommand.js +1 -1
- package/dist/commands/ResetDirectoryCommand.d.ts +1 -1
- package/dist/commands/ResetDirectoryCommand.js +1 -1
- package/dist/commands/RunMeasureCommand.d.ts +1 -1
- package/dist/commands/RunMeasureCommand.js +1 -1
- package/dist/commands/WarmupAppCommand.d.ts +1 -1
- package/dist/commands/WarmupAppCommand.js +1 -1
- package/dist/commands/heap/CheckLeakCommand.d.ts +1 -1
- package/dist/commands/heap/CheckLeakCommand.js +7 -1
- package/dist/commands/heap/GetRetainerTraceCommand.d.ts +1 -1
- package/dist/commands/heap/GetRetainerTraceCommand.js +1 -1
- package/dist/commands/heap/HeapAnalysisCommand.d.ts +1 -1
- package/dist/commands/heap/HeapAnalysisCommand.js +1 -1
- package/dist/commands/heap/HeapAnalysisSubCommandWrapper.d.ts +1 -1
- package/dist/commands/heap/HeapAnalysisSubCommandWrapper.js +1 -1
- package/dist/commands/heap/interactive/InteractiveCommandLoader.d.ts +16 -0
- package/dist/commands/heap/interactive/InteractiveCommandLoader.js +33 -0
- package/dist/commands/heap/interactive/InteractiveHeapCommand.d.ts +28 -0
- package/dist/commands/heap/interactive/InteractiveHeapCommand.js +166 -0
- package/dist/commands/heap/interactive/InteractiveHeapExploreCommand.d.ts +26 -0
- package/dist/commands/heap/interactive/InteractiveHeapExploreCommand.js +145 -0
- package/dist/commands/heap/interactive/ui-components/CliScreen.d.ts +38 -0
- package/dist/commands/heap/interactive/ui-components/CliScreen.js +234 -0
- package/dist/commands/heap/interactive/ui-components/HeapViewController.d.ts +58 -0
- package/dist/commands/heap/interactive/ui-components/HeapViewController.js +251 -0
- package/dist/commands/heap/interactive/ui-components/HeapViewUtils.d.ts +29 -0
- package/dist/commands/heap/interactive/ui-components/HeapViewUtils.js +84 -0
- package/dist/commands/heap/interactive/ui-components/ListComponent.d.ts +62 -0
- package/dist/commands/heap/interactive/ui-components/ListComponent.js +220 -0
- package/dist/commands/helper/GenerateCLIDocCommand.d.ts +1 -1
- package/dist/commands/helper/GenerateCLIDocCommand.js +1 -1
- package/dist/commands/helper/HelperCommand.d.ts +1 -1
- package/dist/commands/helper/HelperCommand.js +17 -5
- package/dist/commands/helper/lib/CommandOrder.d.ts +1 -1
- package/dist/commands/helper/lib/CommandOrder.js +1 -1
- package/dist/commands/helper/lib/Types.d.ts +1 -1
- package/dist/commands/helper/lib/Types.js +1 -1
- package/dist/commands/query/QueryDefaultWorkDirCommand.d.ts +1 -1
- package/dist/commands/query/QueryDefaultWorkDirCommand.js +1 -1
- package/dist/commands/snapshot/CheckXvfbSupportCommand.d.ts +1 -1
- package/dist/commands/snapshot/CheckXvfbSupportCommand.js +1 -1
- package/dist/commands/snapshot/Snapshot.d.ts +1 -1
- package/dist/commands/snapshot/Snapshot.js +1 -1
- package/dist/commands/snapshot/TakeSnapshotCommand.d.ts +1 -1
- package/dist/commands/snapshot/TakeSnapshotCommand.js +1 -1
- package/dist/commands/snapshot/WarmupAndSnapshotCommand.d.ts +1 -1
- package/dist/commands/snapshot/WarmupAndSnapshotCommand.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/options/AppOption.d.ts +1 -1
- package/dist/options/AppOption.js +1 -1
- package/dist/options/DebugOption.d.ts +1 -1
- package/dist/options/DebugOption.js +1 -1
- package/dist/options/DisableXvfbOption.d.ts +1 -1
- package/dist/options/DisableXvfbOption.js +1 -1
- package/dist/options/FullExecutionOption.d.ts +1 -1
- package/dist/options/FullExecutionOption.js +1 -1
- package/dist/options/HeadfulBrowserOption.d.ts +1 -1
- package/dist/options/HeadfulBrowserOption.js +1 -1
- package/dist/options/HeapNodeIdOption.d.ts +1 -1
- package/dist/options/HeapNodeIdOption.js +1 -1
- package/dist/options/HelperOption.d.ts +1 -1
- package/dist/options/HelperOption.js +1 -1
- package/dist/options/InteractionOption.d.ts +1 -1
- package/dist/options/InteractionOption.js +1 -1
- package/dist/options/MLClusteringLinkageMaxDistanceOption.d.ts +18 -0
- package/dist/options/MLClusteringLinkageMaxDistanceOption.js +47 -0
- package/dist/options/MLClusteringMaxDFOption.d.ts +18 -0
- package/dist/options/MLClusteringMaxDFOption.js +47 -0
- package/dist/options/MLClusteringOption.d.ts +18 -0
- package/dist/options/MLClusteringOption.js +37 -0
- package/dist/options/NumberOfRunsOption.d.ts +1 -1
- package/dist/options/NumberOfRunsOption.js +1 -1
- package/dist/options/RemoteBrowserDebugOption.d.ts +1 -1
- package/dist/options/RemoteBrowserDebugOption.js +1 -1
- package/dist/options/RunningModeOption.d.ts +1 -1
- package/dist/options/RunningModeOption.js +1 -1
- package/dist/options/ScenarioFileOption.d.ts +1 -1
- package/dist/options/ScenarioFileOption.js +1 -1
- package/dist/options/SetContinuousTestOption.d.ts +1 -1
- package/dist/options/SetContinuousTestOption.js +1 -1
- package/dist/options/SetDeviceOption.d.ts +1 -1
- package/dist/options/SetDeviceOption.js +1 -1
- package/dist/options/SetWorkingDirectoryOption.d.ts +1 -1
- package/dist/options/SetWorkingDirectoryOption.js +1 -1
- package/dist/options/SilentOption.d.ts +1 -1
- package/dist/options/SilentOption.js +1 -1
- package/dist/options/SkipExtraOperationOption.d.ts +1 -1
- package/dist/options/SkipExtraOperationOption.js +1 -1
- package/dist/options/SkipGCOption.d.ts +1 -1
- package/dist/options/SkipGCOption.js +1 -1
- package/dist/options/SkipScreenshotOption.d.ts +1 -1
- package/dist/options/SkipScreenshotOption.js +1 -1
- package/dist/options/SkipScrollOption.d.ts +1 -1
- package/dist/options/SkipScrollOption.js +1 -1
- package/dist/options/SkipSnapshotOption.d.ts +1 -1
- package/dist/options/SkipSnapshotOption.js +1 -1
- package/dist/options/SkipWarmupOption.d.ts +1 -1
- package/dist/options/SkipWarmupOption.js +1 -1
- package/dist/options/VerboseOption.d.ts +1 -1
- package/dist/options/VerboseOption.js +1 -1
- package/dist/options/heap/BaselineFileOption.d.ts +1 -1
- package/dist/options/heap/BaselineFileOption.js +1 -1
- package/dist/options/heap/FinalFileOption.d.ts +1 -1
- package/dist/options/heap/FinalFileOption.js +1 -1
- package/dist/options/heap/JSEngineOption.d.ts +1 -1
- package/dist/options/heap/JSEngineOption.js +1 -1
- package/dist/options/heap/LeakClusterSizeThresholdOption.d.ts +1 -1
- package/dist/options/heap/LeakClusterSizeThresholdOption.js +1 -1
- package/dist/options/heap/LogTraceAsClusterOption.d.ts +1 -1
- package/dist/options/heap/LogTraceAsClusterOption.js +1 -1
- package/dist/options/heap/OversizeThresholdOption.d.ts +1 -1
- package/dist/options/heap/OversizeThresholdOption.js +1 -1
- package/dist/options/heap/SnapshotDirectoryOption.d.ts +1 -1
- package/dist/options/heap/SnapshotDirectoryOption.js +1 -1
- package/dist/options/heap/SnapshotFileOption.d.ts +1 -1
- package/dist/options/heap/SnapshotFileOption.js +1 -1
- package/dist/options/heap/TargetFileOption.d.ts +1 -1
- package/dist/options/heap/TargetFileOption.js +1 -1
- package/dist/options/heap/TraceAllObjectsOption.d.ts +1 -1
- package/dist/options/heap/TraceAllObjectsOption.js +1 -1
- package/dist/options/heap/leak-filter/LeakFilterFileOption.d.ts +1 -1
- package/dist/options/heap/leak-filter/LeakFilterFileOption.js +1 -1
- package/dist/options/heap/leak-filter/examples/FilterLib.d.ts +1 -1
- package/dist/options/heap/leak-filter/examples/FilterLib.js +1 -1
- package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.d.ts +1 -1
- package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.js +1 -1
- package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.d.ts +1 -1
- package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.js +1 -1
- package/dist/options/heap/leak-filter/examples/large-object-as-leak.example.js +0 -1
- package/dist/options/lib/UniversalOptions.d.ts +1 -1
- package/dist/options/lib/UniversalOptions.js +1 -1
- package/dist/runner.d.ts +1 -1
- package/dist/runner.js +1 -1
- package/package.json +8 -6
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import { CLIOptions } from '@memlab/core';
|
|
11
|
+
import BaseCommand, { CommandCategory } from '../../../BaseCommand';
|
|
12
|
+
import { BaseOption } from '@memlab/core';
|
|
13
|
+
export default class InteractiveHeapCommand extends BaseCommand {
|
|
14
|
+
getCommandName(): string;
|
|
15
|
+
getDescription(): string;
|
|
16
|
+
getCategory(): CommandCategory;
|
|
17
|
+
getExamples(): string[];
|
|
18
|
+
getOptions(): BaseOption[];
|
|
19
|
+
private exitAttempt;
|
|
20
|
+
private printPromptInfo;
|
|
21
|
+
private quit;
|
|
22
|
+
private initPrompt;
|
|
23
|
+
private setupInterruptHandle;
|
|
24
|
+
private setupCommandHandle;
|
|
25
|
+
private startInteractiveCLI;
|
|
26
|
+
run(options: CLIOptions): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=InteractiveHeapCommand.d.ts.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
35
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
36
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
37
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
38
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
39
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
40
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
44
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
const core_1 = require("@memlab/core");
|
|
48
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
49
|
+
const readline_1 = __importDefault(require("readline"));
|
|
50
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
51
|
+
const minimist_1 = __importDefault(require("minimist"));
|
|
52
|
+
const BaseCommand_1 = __importStar(require("../../../BaseCommand"));
|
|
53
|
+
const core_2 = require("@memlab/core");
|
|
54
|
+
const SnapshotFileOption_1 = __importDefault(require("../../../options/heap/SnapshotFileOption"));
|
|
55
|
+
const JSEngineOption_1 = __importDefault(require("../../../options/heap/JSEngineOption"));
|
|
56
|
+
const core_3 = require("@memlab/core");
|
|
57
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
58
|
+
const Dispatcher_1 = require("../../../Dispatcher");
|
|
59
|
+
const InteractiveCommandLoader_1 = __importDefault(require("./InteractiveCommandLoader"));
|
|
60
|
+
class InteractiveHeapCommand extends BaseCommand_1.default {
|
|
61
|
+
constructor() {
|
|
62
|
+
super(...arguments);
|
|
63
|
+
this.exitAttempt = 0;
|
|
64
|
+
}
|
|
65
|
+
getCommandName() {
|
|
66
|
+
return 'heap';
|
|
67
|
+
}
|
|
68
|
+
getDescription() {
|
|
69
|
+
return 'interactive command to explore a single heap snapshot';
|
|
70
|
+
}
|
|
71
|
+
getCategory() {
|
|
72
|
+
return BaseCommand_1.CommandCategory.COMMON;
|
|
73
|
+
}
|
|
74
|
+
getExamples() {
|
|
75
|
+
return ['--snapshot <HEAP_SNAPSHOT_FILE>'];
|
|
76
|
+
}
|
|
77
|
+
getOptions() {
|
|
78
|
+
return [new SnapshotFileOption_1.default(), new JSEngineOption_1.default()];
|
|
79
|
+
}
|
|
80
|
+
printPromptInfo() {
|
|
81
|
+
core_2.info.topLevel(`Heap Snapshot Loaded: ${chalk_1.default.grey(heap_analysis_1.heapConfig.currentHeapFile)}`);
|
|
82
|
+
}
|
|
83
|
+
quit(exitCode = 1) {
|
|
84
|
+
this.exitAttempt = 0;
|
|
85
|
+
core_2.info.topLevel('');
|
|
86
|
+
process.exit(exitCode);
|
|
87
|
+
}
|
|
88
|
+
initPrompt() {
|
|
89
|
+
return readline_1.default.createInterface({
|
|
90
|
+
input: process.stdin,
|
|
91
|
+
output: process.stdout,
|
|
92
|
+
prompt: chalk_1.default.gray('[') + chalk_1.default.green('memlab') + chalk_1.default.gray(']') + '$ ',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
setupInterruptHandle(rl) {
|
|
96
|
+
// exit when user type Ctrl + C
|
|
97
|
+
rl.on('SIGINT', () => {
|
|
98
|
+
if (this.exitAttempt > 0) {
|
|
99
|
+
this.quit();
|
|
100
|
+
}
|
|
101
|
+
this.exitAttempt++;
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
this.exitAttempt--;
|
|
104
|
+
}, 5000);
|
|
105
|
+
core_2.info.topLevel('Type Ctrl + C again to exit');
|
|
106
|
+
rl.prompt();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
setupCommandHandle(rl) {
|
|
110
|
+
// the interactive cli only supports a subset of memlab commands
|
|
111
|
+
const dispatcher = new Dispatcher_1.CommandDispatcher({
|
|
112
|
+
commandLoader: new InteractiveCommandLoader_1.default(),
|
|
113
|
+
});
|
|
114
|
+
// do not halt execution when running the interactive command
|
|
115
|
+
core_2.config.errorHandling = core_1.ErrorHandling.Throw;
|
|
116
|
+
// start interpreting interactive commands
|
|
117
|
+
rl.on('line', (line) => __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
let command = '';
|
|
119
|
+
try {
|
|
120
|
+
// "memlab <command>" -> "<command>"
|
|
121
|
+
command = line.trim().startsWith('memlab ')
|
|
122
|
+
? line.substring('memlab '.length).trim()
|
|
123
|
+
: line.trim();
|
|
124
|
+
if (command === 'exit' || command === 'quit') {
|
|
125
|
+
this.quit(0);
|
|
126
|
+
}
|
|
127
|
+
if (command.length > 0) {
|
|
128
|
+
const args = command.match(/("[^"]+")|('[^']+')|(\S+)/g);
|
|
129
|
+
const parsedArgs = (0, minimist_1.default)(args);
|
|
130
|
+
yield dispatcher.dispatch(parsedArgs);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (ex) {
|
|
134
|
+
const error = core_2.utils.getError(ex);
|
|
135
|
+
core_2.info.topLevel(error.message);
|
|
136
|
+
}
|
|
137
|
+
if (command.length > 0) {
|
|
138
|
+
core_2.info.topLevel('');
|
|
139
|
+
this.printPromptInfo();
|
|
140
|
+
}
|
|
141
|
+
rl.prompt();
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
startInteractiveCLI() {
|
|
145
|
+
// set up the interactive prompt
|
|
146
|
+
const rl = this.initPrompt();
|
|
147
|
+
this.setupInterruptHandle(rl);
|
|
148
|
+
this.setupCommandHandle(rl);
|
|
149
|
+
// start prompt
|
|
150
|
+
this.printPromptInfo();
|
|
151
|
+
rl.prompt();
|
|
152
|
+
}
|
|
153
|
+
run(options) {
|
|
154
|
+
var _a;
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
const workDir = (_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.workDir;
|
|
157
|
+
const reportOutDir = core_3.fileManager.getReportOutDir({ workDir });
|
|
158
|
+
fs_extra_1.default.emptyDirSync(reportOutDir);
|
|
159
|
+
// load single heap snapshot
|
|
160
|
+
heap_analysis_1.heapConfig.isCliInteractiveMode = true;
|
|
161
|
+
yield (0, heap_analysis_1.loadHeapSnapshot)({ args: options.cliArgs });
|
|
162
|
+
this.startInteractiveCLI();
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.default = InteractiveHeapCommand;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import type { CLIOptions } from '@memlab/core';
|
|
11
|
+
import BaseCommand, { CommandCategory } from '../../../BaseCommand';
|
|
12
|
+
import { BaseOption } from '@memlab/core';
|
|
13
|
+
export default class InteractiveHeapViewCommand extends BaseCommand {
|
|
14
|
+
getCommandName(): string;
|
|
15
|
+
getDescription(): string;
|
|
16
|
+
getCategory(): CommandCategory;
|
|
17
|
+
getExamples(): string[];
|
|
18
|
+
getOptions(): BaseOption[];
|
|
19
|
+
private getHeap;
|
|
20
|
+
private getNodesToFocus;
|
|
21
|
+
private getDetachedNodes;
|
|
22
|
+
private getNodesWithLargestRetainedSize;
|
|
23
|
+
private getHeapNodes;
|
|
24
|
+
run(options: CLIOptions): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=InteractiveHeapExploreCommand.d.ts.map
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
35
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
36
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
37
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
38
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
39
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
40
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
44
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
48
|
+
const BaseCommand_1 = __importStar(require("../../../BaseCommand"));
|
|
49
|
+
const core_1 = require("@memlab/core");
|
|
50
|
+
const SnapshotFileOption_1 = __importDefault(require("../../../options/heap/SnapshotFileOption"));
|
|
51
|
+
const JSEngineOption_1 = __importDefault(require("../../../options/heap/JSEngineOption"));
|
|
52
|
+
const core_2 = require("@memlab/core");
|
|
53
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
54
|
+
const CliScreen_1 = __importDefault(require("./ui-components/CliScreen"));
|
|
55
|
+
const HeapNodeIdOption_1 = __importDefault(require("../../../options/HeapNodeIdOption"));
|
|
56
|
+
class InteractiveHeapViewCommand extends BaseCommand_1.default {
|
|
57
|
+
getCommandName() {
|
|
58
|
+
return 'view-heap';
|
|
59
|
+
}
|
|
60
|
+
getDescription() {
|
|
61
|
+
return 'interactive command to view a single heap snapshot';
|
|
62
|
+
}
|
|
63
|
+
getCategory() {
|
|
64
|
+
return BaseCommand_1.CommandCategory.COMMON;
|
|
65
|
+
}
|
|
66
|
+
getExamples() {
|
|
67
|
+
return ['--snapshot <HEAP_SNAPSHOT_FILE>'];
|
|
68
|
+
}
|
|
69
|
+
getOptions() {
|
|
70
|
+
return [
|
|
71
|
+
new SnapshotFileOption_1.default(),
|
|
72
|
+
new JSEngineOption_1.default(),
|
|
73
|
+
new HeapNodeIdOption_1.default(),
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
// get the heap snapshot to view
|
|
77
|
+
getHeap(options) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
// load single heap snapshot
|
|
80
|
+
heap_analysis_1.heapConfig.isCliInteractiveMode = true;
|
|
81
|
+
yield (0, heap_analysis_1.loadHeapSnapshot)({ args: options.cliArgs });
|
|
82
|
+
// get heap
|
|
83
|
+
const heap = heap_analysis_1.heapConfig.currentHeap;
|
|
84
|
+
if (!heap) {
|
|
85
|
+
throw core_1.utils.haltOrThrow('heap snapshot not found, please specify a heap snapshot ' +
|
|
86
|
+
`via --${new SnapshotFileOption_1.default().getOptionName()}`);
|
|
87
|
+
}
|
|
88
|
+
return heap;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
getNodesToFocus(heap) {
|
|
92
|
+
const nodes = this.getNodesWithLargestRetainedSize(heap);
|
|
93
|
+
nodes.push(...this.getDetachedNodes(heap));
|
|
94
|
+
return nodes;
|
|
95
|
+
}
|
|
96
|
+
getDetachedNodes(heap) {
|
|
97
|
+
const ret = [];
|
|
98
|
+
heap.nodes.forEach(node => {
|
|
99
|
+
if (core_1.utils.isDetachedDOMNode(node) || core_1.utils.isDetachedFiberNode(node)) {
|
|
100
|
+
ret.push({ tag: 'Detached', heapObject: node });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return ret;
|
|
104
|
+
}
|
|
105
|
+
getNodesWithLargestRetainedSize(heap) {
|
|
106
|
+
const sizeThreshold = 2 * 1024 * 1024; // 2MB
|
|
107
|
+
const ret = [];
|
|
108
|
+
heap.nodes.forEach(node => {
|
|
109
|
+
if (node.retainedSize >= sizeThreshold && !core_1.utils.isRootNode(node)) {
|
|
110
|
+
ret.push({
|
|
111
|
+
tag: `${core_1.utils.getReadableBytes(node.retainedSize)}`,
|
|
112
|
+
heapObject: node,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return ret;
|
|
117
|
+
}
|
|
118
|
+
// get heap node to focus on
|
|
119
|
+
getHeapNodes(heap) {
|
|
120
|
+
if (core_1.config.focusFiberNodeId >= 0) {
|
|
121
|
+
const node = heap.getNodeById(core_1.config.focusFiberNodeId);
|
|
122
|
+
if (node) {
|
|
123
|
+
return [{ heapObject: node }];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const nodes = this.getNodesToFocus(heap);
|
|
127
|
+
if (nodes.length === 0) {
|
|
128
|
+
throw core_1.utils.haltOrThrow('please specify a heap node ' +
|
|
129
|
+
`via --${new HeapNodeIdOption_1.default().getOptionName()}`);
|
|
130
|
+
}
|
|
131
|
+
return nodes;
|
|
132
|
+
}
|
|
133
|
+
run(options) {
|
|
134
|
+
var _a;
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
const workDir = (_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.workDir;
|
|
137
|
+
const reportOutDir = core_2.fileManager.getReportOutDir({ workDir });
|
|
138
|
+
fs_extra_1.default.emptyDirSync(reportOutDir);
|
|
139
|
+
const heap = yield this.getHeap(options);
|
|
140
|
+
const nodes = this.getHeapNodes(heap);
|
|
141
|
+
new CliScreen_1.default('memlab heap viewer', heap, nodes).start();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.default = InteractiveHeapViewCommand;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IHeapSnapshot } from '@memlab/core';
|
|
2
|
+
import { ComponentDataItem } from './HeapViewUtils';
|
|
3
|
+
export default class CliScreen {
|
|
4
|
+
private screen;
|
|
5
|
+
private objectBox;
|
|
6
|
+
private parentObjectBox;
|
|
7
|
+
private referrerBox;
|
|
8
|
+
private referenceBox;
|
|
9
|
+
private objectPropertyBox;
|
|
10
|
+
private retainerTraceBox;
|
|
11
|
+
private currentFocuseKey;
|
|
12
|
+
private keyToComponent;
|
|
13
|
+
private heapController;
|
|
14
|
+
constructor(title: string, heap: IHeapSnapshot, nodes: ComponentDataItem[]);
|
|
15
|
+
private initScreen;
|
|
16
|
+
private initCallbacks;
|
|
17
|
+
start(): void;
|
|
18
|
+
private registerEvents;
|
|
19
|
+
private registerScreenResize;
|
|
20
|
+
private updateComponentSize;
|
|
21
|
+
private registerKeys;
|
|
22
|
+
private addComponentToFocusKeyMap;
|
|
23
|
+
private getNextFocusKey;
|
|
24
|
+
private getLabel;
|
|
25
|
+
private initParentObjectBox;
|
|
26
|
+
private getParentObjectBoxSize;
|
|
27
|
+
private initReferrerBox;
|
|
28
|
+
private getReferrerBoxSize;
|
|
29
|
+
private initObjectBox;
|
|
30
|
+
private getObjectBoxSize;
|
|
31
|
+
private initObjectPropertyBox;
|
|
32
|
+
private getObjectPropertyBoxSize;
|
|
33
|
+
private initReferenceBox;
|
|
34
|
+
private getReferenceBoxSize;
|
|
35
|
+
private initRetainerTraceBox;
|
|
36
|
+
private getRetainerTraceBoxSize;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=CliScreen.d.ts.map
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const HeapViewUtils_1 = require("./HeapViewUtils");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const blessed_1 = __importDefault(require("blessed"));
|
|
9
|
+
const ListComponent_1 = __importDefault(require("./ListComponent"));
|
|
10
|
+
const HeapViewController_1 = __importDefault(require("./HeapViewController"));
|
|
11
|
+
function positionToNumber(info) {
|
|
12
|
+
return parseInt(`${info}`);
|
|
13
|
+
}
|
|
14
|
+
/*
|
|
15
|
+
* The CliScreen component managers the screen layout
|
|
16
|
+
* all the UI components in CLI.
|
|
17
|
+
*
|
|
18
|
+
* Screen Layout:
|
|
19
|
+
* ┌─Referrers of [*] ─┐┌─Objects ──────────┐┌─References ───────┐
|
|
20
|
+
* │ ││ ││ │
|
|
21
|
+
* │ ││ ││ │
|
|
22
|
+
* │ ││ ││ │
|
|
23
|
+
* │ ││ ││ │
|
|
24
|
+
* │ ││ │└───────────────────┘
|
|
25
|
+
* │ ││ │┌─Retainer Trace ───┐
|
|
26
|
+
* │ ││ ││ │
|
|
27
|
+
* │ ││ ││ │
|
|
28
|
+
* └───────────────────┘│ ││ │
|
|
29
|
+
* ┌─Referrers ────────┐│ ││ │
|
|
30
|
+
* │ ││ ││ │
|
|
31
|
+
* │ │└───────────────────┘│ │
|
|
32
|
+
* │ │┌─Object Detail ────┐│ │
|
|
33
|
+
* │ ││ ││ │
|
|
34
|
+
* │ ││ ││ │
|
|
35
|
+
* │ ││ ││ │
|
|
36
|
+
* │ ││ ││ │
|
|
37
|
+
* │ ││ ││ │
|
|
38
|
+
* └───────────────────┘└───────────────────┘└───────────────────┘
|
|
39
|
+
*/
|
|
40
|
+
class CliScreen {
|
|
41
|
+
constructor(title, heap, nodes) {
|
|
42
|
+
this.currentFocuseKey = 1;
|
|
43
|
+
this.heapController = new HeapViewController_1.default(heap, nodes);
|
|
44
|
+
this.screen = this.initScreen(title);
|
|
45
|
+
const callbacks = this.initCallbacks(this.heapController, this.screen);
|
|
46
|
+
this.keyToComponent = new Map();
|
|
47
|
+
this.referrerBox = this.initReferrerBox(callbacks);
|
|
48
|
+
this.heapController.setReferrerBox(this.referrerBox);
|
|
49
|
+
this.parentObjectBox = this.initParentObjectBox(callbacks);
|
|
50
|
+
this.heapController.setParentBox(this.parentObjectBox);
|
|
51
|
+
this.objectBox = this.initObjectBox(callbacks);
|
|
52
|
+
this.heapController.setObjectBox(this.objectBox);
|
|
53
|
+
this.referenceBox = this.initReferenceBox(callbacks);
|
|
54
|
+
this.heapController.setReferenceBox(this.referenceBox);
|
|
55
|
+
this.objectPropertyBox = this.initObjectPropertyBox(callbacks);
|
|
56
|
+
this.heapController.setObjectPropertyBox(this.objectPropertyBox);
|
|
57
|
+
this.retainerTraceBox = this.initRetainerTraceBox(callbacks);
|
|
58
|
+
this.heapController.setRetainerTraceBox(this.retainerTraceBox);
|
|
59
|
+
this.registerEvents();
|
|
60
|
+
this.heapController.setCurrentHeapObject((0, HeapViewUtils_1.getHeapObjectAt)(nodes, 0));
|
|
61
|
+
}
|
|
62
|
+
initScreen(title) {
|
|
63
|
+
return blessed_1.default.screen({
|
|
64
|
+
smartCSR: true,
|
|
65
|
+
title: title,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
initCallbacks(controller, screen) {
|
|
69
|
+
const selectDebounce = (0, HeapViewUtils_1.debounce)(150);
|
|
70
|
+
const selectCallback = (componentId, index, content, selectInfo) => {
|
|
71
|
+
if (selectInfo.keyName === 'enter') {
|
|
72
|
+
selectDebounce(() => {
|
|
73
|
+
controller.setCurrentHeapObjectFromComponent(componentId, index);
|
|
74
|
+
screen.render();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if (selectInfo.keyName === 'up' || selectInfo.keyName === 'down') {
|
|
78
|
+
selectDebounce(() => {
|
|
79
|
+
controller.setSelectedHeapObjectFromComponent(componentId, index);
|
|
80
|
+
screen.render();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
selectCallback,
|
|
86
|
+
render: () => screen.render(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
start() {
|
|
90
|
+
this.screen.render();
|
|
91
|
+
}
|
|
92
|
+
registerEvents() {
|
|
93
|
+
this.registerKeys();
|
|
94
|
+
this.registerScreenResize();
|
|
95
|
+
}
|
|
96
|
+
registerScreenResize() {
|
|
97
|
+
const screen = this.screen;
|
|
98
|
+
screen.on('resize', () => {
|
|
99
|
+
// all boxes/lists needs to resize
|
|
100
|
+
this.updateComponentSize(this.parentObjectBox, this.getParentObjectBoxSize());
|
|
101
|
+
this.updateComponentSize(this.referrerBox, this.getReferrerBoxSize());
|
|
102
|
+
this.updateComponentSize(this.objectBox, this.getObjectBoxSize());
|
|
103
|
+
this.updateComponentSize(this.objectPropertyBox, this.getObjectPropertyBoxSize());
|
|
104
|
+
this.updateComponentSize(this.referenceBox, this.getReferenceBoxSize());
|
|
105
|
+
this.updateComponentSize(this.retainerTraceBox, this.getRetainerTraceBoxSize());
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
updateComponentSize(component, size) {
|
|
109
|
+
component.element.width = size.width;
|
|
110
|
+
component.element.height = size.height;
|
|
111
|
+
component.element.top = size.top;
|
|
112
|
+
component.element.left = size.left;
|
|
113
|
+
}
|
|
114
|
+
registerKeys() {
|
|
115
|
+
const screen = this.screen;
|
|
116
|
+
// Quit on Escape, q, or Control-C.
|
|
117
|
+
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
|
|
118
|
+
const keyToComponent = this.keyToComponent;
|
|
119
|
+
const heapController = this.heapController;
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
121
|
+
const callback = (char, key) => {
|
|
122
|
+
if (keyToComponent.has(char)) {
|
|
123
|
+
// focus on the selected element
|
|
124
|
+
const component = keyToComponent.get(char);
|
|
125
|
+
if (component) {
|
|
126
|
+
heapController.focusOnComponent(component.id);
|
|
127
|
+
screen.render();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
screen.on('keypress', callback);
|
|
132
|
+
}
|
|
133
|
+
addComponentToFocusKeyMap(component) {
|
|
134
|
+
const key = `${this.currentFocuseKey++}`;
|
|
135
|
+
this.keyToComponent.set(key, component);
|
|
136
|
+
return key;
|
|
137
|
+
}
|
|
138
|
+
getNextFocusKey() {
|
|
139
|
+
return `${this.currentFocuseKey}`;
|
|
140
|
+
}
|
|
141
|
+
getLabel(text, key) {
|
|
142
|
+
return `${text}` + chalk_1.default.grey(` (press ${chalk_1.default.inverse(key)} to focus)`);
|
|
143
|
+
}
|
|
144
|
+
initParentObjectBox(callbacks) {
|
|
145
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getParentObjectBoxSize()), { label: this.getLabel('Referrers of Current', this.getNextFocusKey()) }));
|
|
146
|
+
this.screen.append(box.element);
|
|
147
|
+
this.addComponentToFocusKeyMap(box);
|
|
148
|
+
return box;
|
|
149
|
+
}
|
|
150
|
+
getParentObjectBoxSize() {
|
|
151
|
+
return {
|
|
152
|
+
width: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
153
|
+
height: positionToNumber(this.screen.height) -
|
|
154
|
+
Math.floor(positionToNumber(this.screen.height) / 2),
|
|
155
|
+
top: Math.floor(positionToNumber(this.screen.height) / 2),
|
|
156
|
+
left: 0,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
initReferrerBox(callbacks) {
|
|
160
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getReferrerBoxSize()), { label: this.getLabel('Referrers', this.getNextFocusKey()) }));
|
|
161
|
+
this.screen.append(box.element);
|
|
162
|
+
this.addComponentToFocusKeyMap(box);
|
|
163
|
+
return box;
|
|
164
|
+
}
|
|
165
|
+
getReferrerBoxSize() {
|
|
166
|
+
return {
|
|
167
|
+
width: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
168
|
+
height: Math.floor(positionToNumber(this.screen.height) / 2),
|
|
169
|
+
top: 0,
|
|
170
|
+
left: 0,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
initObjectBox(callbacks) {
|
|
174
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getObjectBoxSize()), { label: this.getLabel('Objects', this.getNextFocusKey()) }));
|
|
175
|
+
this.screen.append(box.element);
|
|
176
|
+
this.addComponentToFocusKeyMap(box);
|
|
177
|
+
return box;
|
|
178
|
+
}
|
|
179
|
+
getObjectBoxSize() {
|
|
180
|
+
return {
|
|
181
|
+
width: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
182
|
+
height: Math.floor((2 * positionToNumber(this.screen.height)) / 3),
|
|
183
|
+
top: 0,
|
|
184
|
+
left: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
initObjectPropertyBox(callbacks) {
|
|
188
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getObjectPropertyBoxSize()), { label: this.getLabel('Object Detail', this.getNextFocusKey()) }));
|
|
189
|
+
this.screen.append(box.element);
|
|
190
|
+
this.addComponentToFocusKeyMap(box);
|
|
191
|
+
return box;
|
|
192
|
+
}
|
|
193
|
+
getObjectPropertyBoxSize() {
|
|
194
|
+
return {
|
|
195
|
+
width: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
196
|
+
height: positionToNumber(this.screen.height) -
|
|
197
|
+
Math.floor((2 * positionToNumber(this.screen.height)) / 3),
|
|
198
|
+
top: Math.floor((2 * positionToNumber(this.screen.height)) / 3),
|
|
199
|
+
left: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
initReferenceBox(callbacks) {
|
|
203
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getReferenceBoxSize()), { label: this.getLabel('References', this.getNextFocusKey()) }));
|
|
204
|
+
this.screen.append(box.element);
|
|
205
|
+
this.addComponentToFocusKeyMap(box);
|
|
206
|
+
return box;
|
|
207
|
+
}
|
|
208
|
+
getReferenceBoxSize() {
|
|
209
|
+
return {
|
|
210
|
+
width: positionToNumber(this.screen.width) -
|
|
211
|
+
Math.floor((2 * positionToNumber(this.screen.width)) / 3),
|
|
212
|
+
height: Math.floor(positionToNumber(this.screen.height) / 3),
|
|
213
|
+
top: 0,
|
|
214
|
+
left: Math.floor((2 * positionToNumber(this.screen.width)) / 3),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
initRetainerTraceBox(callbacks) {
|
|
218
|
+
const box = new ListComponent_1.default([], callbacks, Object.assign(Object.assign({}, this.getRetainerTraceBoxSize()), { label: this.getLabel('Retainer Trace', this.getNextFocusKey()) }));
|
|
219
|
+
this.screen.append(box.element);
|
|
220
|
+
this.addComponentToFocusKeyMap(box);
|
|
221
|
+
return box;
|
|
222
|
+
}
|
|
223
|
+
getRetainerTraceBoxSize() {
|
|
224
|
+
return {
|
|
225
|
+
width: positionToNumber(this.screen.width) -
|
|
226
|
+
Math.floor((2 * positionToNumber(this.screen.width)) / 3),
|
|
227
|
+
height: positionToNumber(this.screen.height) -
|
|
228
|
+
Math.floor(positionToNumber(this.screen.height) / 3),
|
|
229
|
+
top: Math.floor(positionToNumber(this.screen.height) / 3),
|
|
230
|
+
left: Math.floor((2 * positionToNumber(this.screen.width)) / 3),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.default = CliScreen;
|