@memlab/cli 1.0.8 → 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.
Files changed (155) hide show
  1. package/dist/BaseCommand.d.ts +1 -1
  2. package/dist/BaseCommand.js +1 -1
  3. package/dist/CommandLoader.d.ts +1 -1
  4. package/dist/CommandLoader.js +1 -1
  5. package/dist/Dispatcher.d.ts +1 -1
  6. package/dist/Dispatcher.js +1 -1
  7. package/dist/TypesThirdParty.d.ts +1 -1
  8. package/dist/TypesThirdParty.js +1 -1
  9. package/dist/commands/CleanLoggerDataCommand.d.ts +1 -1
  10. package/dist/commands/CleanLoggerDataCommand.js +1 -1
  11. package/dist/commands/CleanRunDataCommand.d.ts +1 -1
  12. package/dist/commands/CleanRunDataCommand.js +1 -1
  13. package/dist/commands/GetVersionCommand.d.ts +1 -1
  14. package/dist/commands/GetVersionCommand.js +1 -1
  15. package/dist/commands/InitDirectoryCommand.d.ts +1 -1
  16. package/dist/commands/InitDirectoryCommand.js +1 -1
  17. package/dist/commands/ListScenariosCommand.d.ts +1 -1
  18. package/dist/commands/ListScenariosCommand.js +1 -1
  19. package/dist/commands/MemLabRunCommand.d.ts +1 -1
  20. package/dist/commands/MemLabRunCommand.js +1 -1
  21. package/dist/commands/PrintSummaryCommand.d.ts +1 -1
  22. package/dist/commands/PrintSummaryCommand.js +1 -1
  23. package/dist/commands/ResetDirectoryCommand.d.ts +1 -1
  24. package/dist/commands/ResetDirectoryCommand.js +1 -1
  25. package/dist/commands/RunMeasureCommand.d.ts +1 -1
  26. package/dist/commands/RunMeasureCommand.js +1 -1
  27. package/dist/commands/WarmupAppCommand.d.ts +1 -1
  28. package/dist/commands/WarmupAppCommand.js +1 -1
  29. package/dist/commands/heap/CheckLeakCommand.d.ts +1 -1
  30. package/dist/commands/heap/CheckLeakCommand.js +1 -1
  31. package/dist/commands/heap/GetRetainerTraceCommand.d.ts +1 -1
  32. package/dist/commands/heap/GetRetainerTraceCommand.js +1 -1
  33. package/dist/commands/heap/HeapAnalysisCommand.d.ts +1 -1
  34. package/dist/commands/heap/HeapAnalysisCommand.js +1 -1
  35. package/dist/commands/heap/HeapAnalysisSubCommandWrapper.d.ts +1 -1
  36. package/dist/commands/heap/HeapAnalysisSubCommandWrapper.js +1 -1
  37. package/dist/commands/heap/interactive/InteractiveCommandLoader.d.ts +1 -1
  38. package/dist/commands/heap/interactive/InteractiveCommandLoader.js +1 -1
  39. package/dist/commands/heap/interactive/InteractiveHeapCommand.d.ts +6 -1
  40. package/dist/commands/heap/interactive/InteractiveHeapCommand.js +54 -15
  41. package/dist/commands/heap/interactive/InteractiveHeapExploreCommand.d.ts +26 -0
  42. package/dist/commands/heap/interactive/InteractiveHeapExploreCommand.js +145 -0
  43. package/dist/commands/heap/interactive/ui-components/CliScreen.d.ts +38 -0
  44. package/dist/commands/heap/interactive/ui-components/CliScreen.js +234 -0
  45. package/dist/commands/heap/interactive/ui-components/HeapViewController.d.ts +58 -0
  46. package/dist/commands/heap/interactive/ui-components/HeapViewController.js +251 -0
  47. package/dist/commands/heap/interactive/ui-components/HeapViewUtils.d.ts +29 -0
  48. package/dist/commands/heap/interactive/ui-components/HeapViewUtils.js +84 -0
  49. package/dist/commands/heap/interactive/ui-components/ListComponent.d.ts +62 -0
  50. package/dist/commands/heap/interactive/ui-components/ListComponent.js +220 -0
  51. package/dist/commands/helper/GenerateCLIDocCommand.d.ts +1 -1
  52. package/dist/commands/helper/GenerateCLIDocCommand.js +1 -1
  53. package/dist/commands/helper/HelperCommand.d.ts +1 -1
  54. package/dist/commands/helper/HelperCommand.js +1 -1
  55. package/dist/commands/helper/lib/CommandOrder.d.ts +1 -1
  56. package/dist/commands/helper/lib/CommandOrder.js +1 -1
  57. package/dist/commands/helper/lib/Types.d.ts +1 -1
  58. package/dist/commands/helper/lib/Types.js +1 -1
  59. package/dist/commands/query/QueryDefaultWorkDirCommand.d.ts +1 -1
  60. package/dist/commands/query/QueryDefaultWorkDirCommand.js +1 -1
  61. package/dist/commands/snapshot/CheckXvfbSupportCommand.d.ts +1 -1
  62. package/dist/commands/snapshot/CheckXvfbSupportCommand.js +1 -1
  63. package/dist/commands/snapshot/Snapshot.d.ts +1 -1
  64. package/dist/commands/snapshot/Snapshot.js +1 -1
  65. package/dist/commands/snapshot/TakeSnapshotCommand.d.ts +1 -1
  66. package/dist/commands/snapshot/TakeSnapshotCommand.js +1 -1
  67. package/dist/commands/snapshot/WarmupAndSnapshotCommand.d.ts +1 -1
  68. package/dist/commands/snapshot/WarmupAndSnapshotCommand.js +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.js +1 -1
  71. package/dist/options/AppOption.d.ts +1 -1
  72. package/dist/options/AppOption.js +1 -1
  73. package/dist/options/DebugOption.d.ts +1 -1
  74. package/dist/options/DebugOption.js +1 -1
  75. package/dist/options/DisableXvfbOption.d.ts +1 -1
  76. package/dist/options/DisableXvfbOption.js +1 -1
  77. package/dist/options/FullExecutionOption.d.ts +1 -1
  78. package/dist/options/FullExecutionOption.js +1 -1
  79. package/dist/options/HeadfulBrowserOption.d.ts +1 -1
  80. package/dist/options/HeadfulBrowserOption.js +1 -1
  81. package/dist/options/HeapNodeIdOption.d.ts +1 -1
  82. package/dist/options/HeapNodeIdOption.js +1 -1
  83. package/dist/options/HelperOption.d.ts +1 -1
  84. package/dist/options/HelperOption.js +1 -1
  85. package/dist/options/InteractionOption.d.ts +1 -1
  86. package/dist/options/InteractionOption.js +1 -1
  87. package/dist/options/MLClusteringLinkageMaxDistanceOption.d.ts +1 -1
  88. package/dist/options/MLClusteringLinkageMaxDistanceOption.js +1 -1
  89. package/dist/options/MLClusteringMaxDFOption.d.ts +1 -1
  90. package/dist/options/MLClusteringMaxDFOption.js +1 -1
  91. package/dist/options/MLClusteringOption.d.ts +1 -1
  92. package/dist/options/MLClusteringOption.js +1 -1
  93. package/dist/options/NumberOfRunsOption.d.ts +1 -1
  94. package/dist/options/NumberOfRunsOption.js +1 -1
  95. package/dist/options/RemoteBrowserDebugOption.d.ts +1 -1
  96. package/dist/options/RemoteBrowserDebugOption.js +1 -1
  97. package/dist/options/RunningModeOption.d.ts +1 -1
  98. package/dist/options/RunningModeOption.js +1 -1
  99. package/dist/options/ScenarioFileOption.d.ts +1 -1
  100. package/dist/options/ScenarioFileOption.js +1 -1
  101. package/dist/options/SetContinuousTestOption.d.ts +1 -1
  102. package/dist/options/SetContinuousTestOption.js +1 -1
  103. package/dist/options/SetDeviceOption.d.ts +1 -1
  104. package/dist/options/SetDeviceOption.js +1 -1
  105. package/dist/options/SetWorkingDirectoryOption.d.ts +1 -1
  106. package/dist/options/SetWorkingDirectoryOption.js +1 -1
  107. package/dist/options/SilentOption.d.ts +1 -1
  108. package/dist/options/SilentOption.js +1 -1
  109. package/dist/options/SkipExtraOperationOption.d.ts +1 -1
  110. package/dist/options/SkipExtraOperationOption.js +1 -1
  111. package/dist/options/SkipGCOption.d.ts +1 -1
  112. package/dist/options/SkipGCOption.js +1 -1
  113. package/dist/options/SkipScreenshotOption.d.ts +1 -1
  114. package/dist/options/SkipScreenshotOption.js +1 -1
  115. package/dist/options/SkipScrollOption.d.ts +1 -1
  116. package/dist/options/SkipScrollOption.js +1 -1
  117. package/dist/options/SkipSnapshotOption.d.ts +1 -1
  118. package/dist/options/SkipSnapshotOption.js +1 -1
  119. package/dist/options/SkipWarmupOption.d.ts +1 -1
  120. package/dist/options/SkipWarmupOption.js +1 -1
  121. package/dist/options/VerboseOption.d.ts +1 -1
  122. package/dist/options/VerboseOption.js +1 -1
  123. package/dist/options/heap/BaselineFileOption.d.ts +1 -1
  124. package/dist/options/heap/BaselineFileOption.js +1 -1
  125. package/dist/options/heap/FinalFileOption.d.ts +1 -1
  126. package/dist/options/heap/FinalFileOption.js +1 -1
  127. package/dist/options/heap/JSEngineOption.d.ts +1 -1
  128. package/dist/options/heap/JSEngineOption.js +1 -1
  129. package/dist/options/heap/LeakClusterSizeThresholdOption.d.ts +1 -1
  130. package/dist/options/heap/LeakClusterSizeThresholdOption.js +1 -1
  131. package/dist/options/heap/LogTraceAsClusterOption.d.ts +1 -1
  132. package/dist/options/heap/LogTraceAsClusterOption.js +1 -1
  133. package/dist/options/heap/OversizeThresholdOption.d.ts +1 -1
  134. package/dist/options/heap/OversizeThresholdOption.js +1 -1
  135. package/dist/options/heap/SnapshotDirectoryOption.d.ts +1 -1
  136. package/dist/options/heap/SnapshotDirectoryOption.js +1 -1
  137. package/dist/options/heap/SnapshotFileOption.d.ts +1 -1
  138. package/dist/options/heap/SnapshotFileOption.js +1 -1
  139. package/dist/options/heap/TargetFileOption.d.ts +1 -1
  140. package/dist/options/heap/TargetFileOption.js +1 -1
  141. package/dist/options/heap/TraceAllObjectsOption.d.ts +1 -1
  142. package/dist/options/heap/TraceAllObjectsOption.js +1 -1
  143. package/dist/options/heap/leak-filter/LeakFilterFileOption.d.ts +1 -1
  144. package/dist/options/heap/leak-filter/LeakFilterFileOption.js +1 -1
  145. package/dist/options/heap/leak-filter/examples/FilterLib.d.ts +1 -1
  146. package/dist/options/heap/leak-filter/examples/FilterLib.js +1 -1
  147. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.d.ts +1 -1
  148. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.js +1 -1
  149. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.d.ts +1 -1
  150. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.js +1 -1
  151. package/dist/options/lib/UniversalOptions.d.ts +1 -1
  152. package/dist/options/lib/UniversalOptions.js +1 -1
  153. package/dist/runner.d.ts +1 -1
  154. package/dist/runner.js +1 -1
  155. package/package.json +3 -1
@@ -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;
@@ -0,0 +1,58 @@
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 { IHeapSnapshot, IHeapNode } from '@memlab/core';
11
+ import type ListComponent from './ListComponent';
12
+ import { ComponentDataItem, ComponentData } from './HeapViewUtils';
13
+ declare type SelectHeapObjectOption = {
14
+ noChangeInReferenceBox?: boolean;
15
+ noChangeInReferrerBox?: boolean;
16
+ noChangeInRetainerTraceBox?: boolean;
17
+ noChangeInObjectPropertyBox?: boolean;
18
+ };
19
+ /**
20
+ * HeapViewController managers all the data associated with each
21
+ * UI components in CLI and coordinates the events/interaction
22
+ * among all UI components.
23
+ */
24
+ export default class HeapViewController {
25
+ private currentHeapObject;
26
+ private selectedHeapObject;
27
+ private currentHeapObjectsInfo;
28
+ private componentIdToDataMap;
29
+ private componentIdToComponentMap;
30
+ private heap;
31
+ private parentBox;
32
+ private referrerBox;
33
+ private objectBox;
34
+ private referenceBox;
35
+ private objectPropertyBox;
36
+ private retainerTracePropertyBox;
37
+ constructor(heap: IHeapSnapshot, nodes: ComponentDataItem[]);
38
+ getContent(componentId: number): string[];
39
+ setParentBox(component: ListComponent): void;
40
+ setReferrerBox(component: ListComponent): void;
41
+ getReferrerBoxData(node?: IHeapNode): ComponentData;
42
+ setObjectBox(component: ListComponent): void;
43
+ getObjectBoxData(): ComponentData;
44
+ setReferenceBox(component: ListComponent): void;
45
+ getReferenceBoxData(): ComponentData;
46
+ setObjectPropertyBox(component: ListComponent): void;
47
+ getObjectPropertyData(): ComponentData;
48
+ private getKeyValuePairString;
49
+ setRetainerTraceBox(component: ListComponent): void;
50
+ getRetainerTraceData(): ComponentData;
51
+ setCurrentHeapObjectFromComponent(componentId: number, itemIndex: number): void;
52
+ setCurrentHeapObject(node: IHeapNode): void;
53
+ focusOnComponent(componentId: number): void;
54
+ setSelectedHeapObjectFromComponent(componentId: number, itemIndex: number): void;
55
+ setSelectedHeapObject(node: IHeapNode, options?: SelectHeapObjectOption): void;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=HeapViewController.d.ts.map