@memlab/cli 1.0.23 → 1.0.24
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/dist/BaseCommand.d.ts +1 -0
- package/dist/BaseCommand.js +6 -0
- package/dist/commands/RunMeasureCommand.js +1 -2
- package/dist/commands/heap/CheckLeakCommand.d.ts +10 -0
- package/dist/commands/heap/CheckLeakCommand.js +32 -9
- package/dist/commands/heap/DiffLeakCommand.d.ts +1 -2
- package/dist/commands/heap/DiffLeakCommand.js +10 -16
- package/dist/commands/heap/interactive/ui-components/CliScreen.d.ts +5 -0
- package/dist/commands/heap/interactive/ui-components/CliScreen.js +51 -11
- package/dist/commands/heap/interactive/ui-components/HeapViewController.d.ts +2 -0
- package/dist/commands/heap/interactive/ui-components/HeapViewController.js +5 -1
- package/dist/commands/heap/interactive/ui-components/ListComponent.js +1 -0
- package/dist/commands/helper/GenerateCLIDocCommand.js +6 -1
- package/dist/commands/helper/HelperCommand.js +18 -15
- package/dist/lib/CLIUtils.d.ts +22 -0
- package/dist/lib/CLIUtils.js +129 -0
- package/dist/options/MLClusteringOption.d.ts +1 -0
- package/dist/options/MLClusteringOption.js +4 -0
- package/dist/options/NumberOfRunsOption.d.ts +4 -2
- package/dist/options/NumberOfRunsOption.js +12 -4
- package/dist/options/experiment/SetControlWorkDirOption.d.ts +2 -1
- package/dist/options/experiment/SetControlWorkDirOption.js +25 -6
- package/dist/options/experiment/SetTreatmentWorkDirOption.js +6 -0
- package/dist/options/heap/TraceAllObjectsOption.js +8 -2
- package/package.json +1 -1
package/dist/BaseCommand.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export default class BaseCommand extends Command {
|
|
|
27
27
|
getExamples(): string[];
|
|
28
28
|
getCategory(): CommandCategory;
|
|
29
29
|
getDescription(): string;
|
|
30
|
+
getDocumenation(): string;
|
|
30
31
|
getPrerequisites(): BaseCommand[];
|
|
31
32
|
isInternalCommand(): boolean;
|
|
32
33
|
getOptions(): BaseOption[];
|
package/dist/BaseCommand.js
CHANGED
|
@@ -101,6 +101,12 @@ class BaseCommand extends Command {
|
|
|
101
101
|
const className = this.constructor.name;
|
|
102
102
|
throw new Error(`${className}.getDescription is not implemented`);
|
|
103
103
|
}
|
|
104
|
+
// More detailed description or documentation about this command.
|
|
105
|
+
// This will be printed as helper text in CLI for a specific command.
|
|
106
|
+
// Documentation generator will also use the description returned here.
|
|
107
|
+
getDocumenation() {
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
104
110
|
// get a sequence of commands that must be executed before
|
|
105
111
|
// running this command
|
|
106
112
|
getPrerequisites() {
|
|
@@ -86,9 +86,8 @@ class RunMeasureCommand extends BaseCommand_1.default {
|
|
|
86
86
|
];
|
|
87
87
|
}
|
|
88
88
|
run(options) {
|
|
89
|
-
var _a, _b;
|
|
90
89
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
const numRuns = (
|
|
90
|
+
const numRuns = NumberOfRunsOption_1.default.getParsedOption(options.configFromOptions);
|
|
92
91
|
core_1.config.runningMode = core_1.modes.get('measure', core_1.config);
|
|
93
92
|
for (let i = 0; i < numRuns; ++i) {
|
|
94
93
|
yield (0, Snapshot_1.runPageInteractionFromCLI)();
|
|
@@ -7,11 +7,21 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
+
import type { ParsedArgs } from 'minimist';
|
|
10
11
|
import type { BaseOption, CLIOptions } from '@memlab/core';
|
|
11
12
|
import BaseCommand, { CommandCategory } from '../../BaseCommand';
|
|
13
|
+
export declare type CheckLeakCommandOptions = {
|
|
14
|
+
isMLClustering?: boolean;
|
|
15
|
+
};
|
|
12
16
|
export default class CheckLeakCommand extends BaseCommand {
|
|
17
|
+
private isMLClustering;
|
|
18
|
+
private isMLClusteringSettingCache;
|
|
19
|
+
protected useDefaultMLClusteringSetting(cliArgs: ParsedArgs): void;
|
|
20
|
+
protected restoreDefaultMLClusteringSetting(cliArgs: ParsedArgs): void;
|
|
21
|
+
constructor(options?: CheckLeakCommandOptions);
|
|
13
22
|
getCommandName(): string;
|
|
14
23
|
getDescription(): string;
|
|
24
|
+
getDocumenation(): string;
|
|
15
25
|
getCategory(): CommandCategory;
|
|
16
26
|
getPrerequisites(): BaseCommand[];
|
|
17
27
|
getOptions(): BaseOption[];
|
|
@@ -1,13 +1,4 @@
|
|
|
1
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 web_perf_infra
|
|
10
|
-
*/
|
|
11
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
3
|
if (k2 === undefined) k2 = k;
|
|
13
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -64,12 +55,37 @@ const MLClusteringMaxDFOption_1 = __importDefault(require("../../options/MLClust
|
|
|
64
55
|
const CleanupSnapshotOption_1 = __importDefault(require("../../options/heap/CleanupSnapshotOption"));
|
|
65
56
|
const SetWorkingDirectoryOption_1 = __importDefault(require("../../options/SetWorkingDirectoryOption"));
|
|
66
57
|
class CheckLeakCommand extends BaseCommand_1.default {
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
super();
|
|
60
|
+
this.isMLClustering = false;
|
|
61
|
+
this.isMLClusteringSettingCache = false;
|
|
62
|
+
this.isMLClustering = !!(options === null || options === void 0 ? void 0 : options.isMLClustering);
|
|
63
|
+
}
|
|
64
|
+
useDefaultMLClusteringSetting(cliArgs) {
|
|
65
|
+
if (!MLClusteringOption_1.default.hasOptionSet(cliArgs)) {
|
|
66
|
+
core_1.config.isMLClustering = this.isMLClustering;
|
|
67
|
+
this.isMLClusteringSettingCache = core_1.config.isMLClustering;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
restoreDefaultMLClusteringSetting(cliArgs) {
|
|
71
|
+
if (!MLClusteringOption_1.default.hasOptionSet(cliArgs)) {
|
|
72
|
+
core_1.config.isMLClustering = this.isMLClusteringSettingCache;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
67
75
|
getCommandName() {
|
|
68
76
|
return 'find-leaks';
|
|
69
77
|
}
|
|
70
78
|
getDescription() {
|
|
71
79
|
return 'find memory leaks in heap snapshots';
|
|
72
80
|
}
|
|
81
|
+
getDocumenation() {
|
|
82
|
+
return `There are three ways to specify inputs for the \`memlab find-leaks\` command:
|
|
83
|
+
1. \`--baseline\`, \`--target\`, \`--final\` specifies each snapshot input individually;
|
|
84
|
+
2. \`--snapshot-dir\` specifies the directory that holds all three heap snapshot files (MemLab will assign baseline, target, and final based on alphabetic order of the file);
|
|
85
|
+
3. \`--work-dir\` specifies the output working directory of the \`memlab run\` or the \`memlab snapshot\` command;
|
|
86
|
+
|
|
87
|
+
Please only use one of the three ways to specify the input.`;
|
|
88
|
+
}
|
|
73
89
|
getCategory() {
|
|
74
90
|
return BaseCommand_1.CommandCategory.COMMON;
|
|
75
91
|
}
|
|
@@ -100,8 +116,15 @@ class CheckLeakCommand extends BaseCommand_1.default {
|
|
|
100
116
|
return __awaiter(this, void 0, void 0, function* () {
|
|
101
117
|
const workDir = (_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.workDir;
|
|
102
118
|
core_1.fileManager.initDirs(core_1.config, { workDir });
|
|
119
|
+
const { runMetaInfoManager } = core_1.runInfoUtils;
|
|
120
|
+
runMetaInfoManager.setConfigFromRunMeta({
|
|
121
|
+
workDir,
|
|
122
|
+
silentFail: true,
|
|
123
|
+
});
|
|
103
124
|
core_1.config.chaseWeakMapEdge = false;
|
|
125
|
+
this.useDefaultMLClusteringSetting(options.cliArgs);
|
|
104
126
|
yield core_1.analysis.checkLeak();
|
|
127
|
+
this.restoreDefaultMLClusteringSetting(options.cliArgs);
|
|
105
128
|
const configFromOptions = (_b = options.configFromOptions) !== null && _b !== void 0 ? _b : {};
|
|
106
129
|
if (configFromOptions['cleanUpSnapshot']) {
|
|
107
130
|
core_1.fileManager.removeSnapshotFiles();
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import { CLIOptions } from '@memlab/core';
|
|
10
|
+
import type { BaseOption, CLIOptions } from '@memlab/core';
|
|
11
11
|
import BaseCommand, { CommandCategory } from '../../BaseCommand';
|
|
12
|
-
import { BaseOption } from '@memlab/core';
|
|
13
12
|
export default class CheckLeakCommand extends BaseCommand {
|
|
14
13
|
getCommandName(): string;
|
|
15
14
|
getDescription(): string;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
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 web_perf_infra
|
|
10
|
-
*/
|
|
11
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
3
|
if (k2 === undefined) k2 = k;
|
|
13
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -45,9 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
36
|
};
|
|
46
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
38
|
const core_1 = require("@memlab/core");
|
|
48
|
-
const core_2 = require("@memlab/core");
|
|
49
39
|
const BaseCommand_1 = __importStar(require("../../BaseCommand"));
|
|
50
|
-
const core_3 = require("@memlab/core");
|
|
51
40
|
const JSEngineOption_1 = __importDefault(require("../../options/heap/JSEngineOption"));
|
|
52
41
|
const InitDirectoryCommand_1 = __importDefault(require("../InitDirectoryCommand"));
|
|
53
42
|
const OversizeThresholdOption_1 = __importDefault(require("../../options/heap/OversizeThresholdOption"));
|
|
@@ -92,18 +81,23 @@ class CheckLeakCommand extends BaseCommand_1.default {
|
|
|
92
81
|
run(options) {
|
|
93
82
|
var _a, _b;
|
|
94
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
|
|
84
|
+
core_1.config.chaseWeakMapEdge = false;
|
|
96
85
|
// double check parameters
|
|
97
|
-
if (!((_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.
|
|
86
|
+
if (!((_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.controlWorkDirs) ||
|
|
98
87
|
!((_b = options.configFromOptions) === null || _b === void 0 ? void 0 : _b.treatmentWorkDir)) {
|
|
99
|
-
|
|
88
|
+
core_1.info.error('Please specify control and test working directory');
|
|
100
89
|
throw core_1.utils.haltOrThrow('No control or test working directory specified');
|
|
101
90
|
}
|
|
102
91
|
// get parameters
|
|
103
|
-
const
|
|
92
|
+
const controlWorkDirs = options.configFromOptions['controlWorkDirs'];
|
|
104
93
|
const treatmentWorkDir = options.configFromOptions['treatmentWorkDir'];
|
|
94
|
+
const { runMetaInfoManager } = core_1.runInfoUtils;
|
|
95
|
+
runMetaInfoManager.setConfigFromRunMeta({
|
|
96
|
+
workDir: treatmentWorkDir,
|
|
97
|
+
silentFail: true,
|
|
98
|
+
});
|
|
105
99
|
// diff memory leaks
|
|
106
|
-
yield
|
|
100
|
+
yield core_1.analysis.diffLeakByWorkDir({ controlWorkDirs, treatmentWorkDir });
|
|
107
101
|
});
|
|
108
102
|
}
|
|
109
103
|
}
|
|
@@ -12,6 +12,7 @@ export default class CliScreen {
|
|
|
12
12
|
private currentFocuseKey;
|
|
13
13
|
private keyToComponent;
|
|
14
14
|
private heapController;
|
|
15
|
+
private fullScreenComponent;
|
|
15
16
|
constructor(title: string, heap: IHeapSnapshot, objectCategory: Map<string, ComponentDataItem[]>);
|
|
16
17
|
private setFirstObjectAsCurrrent;
|
|
17
18
|
private initScreen;
|
|
@@ -19,9 +20,12 @@ export default class CliScreen {
|
|
|
19
20
|
start(): void;
|
|
20
21
|
private registerEvents;
|
|
21
22
|
private registerScreenResize;
|
|
23
|
+
private updateAllComponentsSize;
|
|
22
24
|
private updateComponentSize;
|
|
23
25
|
private updateElementSize;
|
|
24
26
|
private registerKeys;
|
|
27
|
+
private makeComponentFullScreen;
|
|
28
|
+
private makeNoComponentFullScreen;
|
|
25
29
|
private addComponentToFocusKeyMap;
|
|
26
30
|
private getNextFocusKey;
|
|
27
31
|
private initClusteredObjectBox;
|
|
@@ -29,6 +33,7 @@ export default class CliScreen {
|
|
|
29
33
|
private initReferrerBox;
|
|
30
34
|
private getReferrerBoxSize;
|
|
31
35
|
private initObjectBox;
|
|
36
|
+
private getComponentFullScreenSize;
|
|
32
37
|
private getObjectBoxSize;
|
|
33
38
|
private initObjectPropertyBox;
|
|
34
39
|
private getObjectPropertyBoxSize;
|
|
@@ -40,6 +40,7 @@ function positionToNumber(info) {
|
|
|
40
40
|
class CliScreen {
|
|
41
41
|
constructor(title, heap, objectCategory) {
|
|
42
42
|
this.currentFocuseKey = 1;
|
|
43
|
+
this.fullScreenComponent = null;
|
|
43
44
|
this.heapController = new HeapViewController_1.default(heap, objectCategory);
|
|
44
45
|
this.screen = this.initScreen(title);
|
|
45
46
|
const callbacks = this.initCallbacks(this.heapController, this.screen);
|
|
@@ -118,16 +119,20 @@ class CliScreen {
|
|
|
118
119
|
}
|
|
119
120
|
registerScreenResize() {
|
|
120
121
|
const screen = this.screen;
|
|
121
|
-
screen.on('resize', ()
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
screen.on('resize', this.updateAllComponentsSize.bind(this));
|
|
123
|
+
}
|
|
124
|
+
updateAllComponentsSize() {
|
|
125
|
+
// all boxes/lists needs to resize
|
|
126
|
+
this.updateComponentSize(this.clusteredObjectBox, this.getClusteredObjectBoxSize());
|
|
127
|
+
this.updateComponentSize(this.referrerBox, this.getReferrerBoxSize());
|
|
128
|
+
this.updateComponentSize(this.objectBox, this.getObjectBoxSize());
|
|
129
|
+
this.updateComponentSize(this.objectPropertyBox, this.getObjectPropertyBoxSize());
|
|
130
|
+
this.updateComponentSize(this.referenceBox, this.getReferenceBoxSize());
|
|
131
|
+
this.updateComponentSize(this.retainerTraceBox, this.getRetainerTraceBoxSize());
|
|
132
|
+
if (this.fullScreenComponent != null) {
|
|
133
|
+
this.updateComponentSize(this.fullScreenComponent, this.getComponentFullScreenSize());
|
|
134
|
+
}
|
|
135
|
+
this.updateElementSize(this.helperTextElement, this.getHelperTextSize());
|
|
131
136
|
}
|
|
132
137
|
updateComponentSize(component, size) {
|
|
133
138
|
this.updateElementSize(component.element, size);
|
|
@@ -141,7 +146,16 @@ class CliScreen {
|
|
|
141
146
|
registerKeys() {
|
|
142
147
|
const screen = this.screen;
|
|
143
148
|
// Quit on Escape, q, or Control-C.
|
|
144
|
-
screen.key(['escape', 'q', 'C-c'], () =>
|
|
149
|
+
screen.key(['escape', 'q', 'C-c'], () => {
|
|
150
|
+
if (this.fullScreenComponent != null) {
|
|
151
|
+
// exit component full screen mode
|
|
152
|
+
this.makeNoComponentFullScreen();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// quit the program
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
145
159
|
const keyToComponent = this.keyToComponent;
|
|
146
160
|
const heapController = this.heapController;
|
|
147
161
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -150,13 +164,30 @@ class CliScreen {
|
|
|
150
164
|
// focus on the selected element
|
|
151
165
|
const component = keyToComponent.get(char);
|
|
152
166
|
if (component) {
|
|
167
|
+
if (component !== this.fullScreenComponent) {
|
|
168
|
+
// quit full screen mode if the component to focus
|
|
169
|
+
// is not the current full screen component
|
|
170
|
+
this.makeNoComponentFullScreen();
|
|
171
|
+
}
|
|
153
172
|
heapController.focusOnComponent(component.id);
|
|
154
173
|
screen.render();
|
|
155
174
|
}
|
|
156
175
|
}
|
|
176
|
+
// enter full screen
|
|
177
|
+
if (char === 'f') {
|
|
178
|
+
this.makeComponentFullScreen(heapController.getFocusedComponent());
|
|
179
|
+
}
|
|
157
180
|
};
|
|
158
181
|
screen.on('keypress', callback);
|
|
159
182
|
}
|
|
183
|
+
makeComponentFullScreen(component) {
|
|
184
|
+
this.fullScreenComponent = component;
|
|
185
|
+
this.updateAllComponentsSize();
|
|
186
|
+
}
|
|
187
|
+
makeNoComponentFullScreen() {
|
|
188
|
+
this.fullScreenComponent = null;
|
|
189
|
+
this.updateAllComponentsSize();
|
|
190
|
+
}
|
|
160
191
|
addComponentToFocusKeyMap(component) {
|
|
161
192
|
const key = `${this.currentFocuseKey++}`;
|
|
162
193
|
this.keyToComponent.set(key, component);
|
|
@@ -208,6 +239,14 @@ class CliScreen {
|
|
|
208
239
|
this.addComponentToFocusKeyMap(box);
|
|
209
240
|
return box;
|
|
210
241
|
}
|
|
242
|
+
getComponentFullScreenSize() {
|
|
243
|
+
return {
|
|
244
|
+
width: positionToNumber(this.screen.width) - 4,
|
|
245
|
+
height: positionToNumber(this.screen.height) - 5,
|
|
246
|
+
top: 2,
|
|
247
|
+
left: 2,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
211
250
|
getObjectBoxSize() {
|
|
212
251
|
return {
|
|
213
252
|
width: Math.floor(positionToNumber(this.screen.width) / 3),
|
|
@@ -282,6 +321,7 @@ class CliScreen {
|
|
|
282
321
|
'←': '',
|
|
283
322
|
'→': '',
|
|
284
323
|
Enter: 'select',
|
|
324
|
+
f: 'full screen',
|
|
285
325
|
q: 'quit',
|
|
286
326
|
};
|
|
287
327
|
const keysToFocus = Array.from(this.keyToComponent.keys());
|
|
@@ -22,6 +22,7 @@ export default class HeapViewController {
|
|
|
22
22
|
private componentIdToDataMap;
|
|
23
23
|
private componentIdToComponentMap;
|
|
24
24
|
private heap;
|
|
25
|
+
private focusedComponent;
|
|
25
26
|
private clusteredBox;
|
|
26
27
|
private referrerBox;
|
|
27
28
|
private objectBox;
|
|
@@ -30,6 +31,7 @@ export default class HeapViewController {
|
|
|
30
31
|
private retainerTracePropertyBox;
|
|
31
32
|
private scriptManager;
|
|
32
33
|
constructor(heap: IHeapSnapshot, objectCategory: ObjectCategory);
|
|
34
|
+
getFocusedComponent(): ListComponent;
|
|
33
35
|
private getFlattenHeapObjectsInfo;
|
|
34
36
|
private getFlattenClusteredObjectsInfo;
|
|
35
37
|
private shouldClusterCategory;
|
|
@@ -27,6 +27,9 @@ class HeapViewController {
|
|
|
27
27
|
this.scriptManager = new e2e_1.ScriptManager();
|
|
28
28
|
this.scriptManager.loadFromFiles();
|
|
29
29
|
}
|
|
30
|
+
getFocusedComponent() {
|
|
31
|
+
return this.focusedComponent;
|
|
32
|
+
}
|
|
30
33
|
getFlattenHeapObjectsInfo(objectCategory) {
|
|
31
34
|
let ret = [];
|
|
32
35
|
for (const category of objectCategory.keys()) {
|
|
@@ -341,7 +344,7 @@ class HeapViewController {
|
|
|
341
344
|
this.objectBox.setLabel('Objects');
|
|
342
345
|
this.setSelectedHeapObject(node);
|
|
343
346
|
if (!options.skipFocus) {
|
|
344
|
-
this.focusOnComponent(this.
|
|
347
|
+
this.focusOnComponent(this.clusteredBox.id);
|
|
345
348
|
}
|
|
346
349
|
}
|
|
347
350
|
focusOnComponent(componentId) {
|
|
@@ -349,6 +352,7 @@ class HeapViewController {
|
|
|
349
352
|
for (const component of this.componentIdToComponentMap.values()) {
|
|
350
353
|
if (component.id === componentId) {
|
|
351
354
|
component.focus();
|
|
355
|
+
this.focusedComponent = component;
|
|
352
356
|
const data = this.componentIdToDataMap.get(componentId);
|
|
353
357
|
const selectIndex = (_a = (data && data.selectedIdx)) !== null && _a !== void 0 ? _a : -1;
|
|
354
358
|
this.setSelectedHeapObjectFromComponent(componentId, selectIndex);
|
|
@@ -132,11 +132,16 @@ class GenerateCLIDocCommand extends BaseCommand_1.default {
|
|
|
132
132
|
}
|
|
133
133
|
writeCommand(docFile, command, indent = '') {
|
|
134
134
|
const name = command.getFullCommand();
|
|
135
|
-
const desc = core_1.utils.upperCaseFirstCharacter(command.getDescription());
|
|
135
|
+
const desc = core_1.utils.upperCaseFirstCharacter(command.getDescription().trim());
|
|
136
|
+
const cmdDoc = command.getDocumenation().trim();
|
|
136
137
|
// write command title
|
|
137
138
|
this.writeTextWithNewLine(docFile, `\n###${indent} memlab ${name}\n`);
|
|
138
139
|
// write description
|
|
139
140
|
this.writeTextWithNewLine(docFile, `${desc}\n`);
|
|
141
|
+
// write detailed command documentation
|
|
142
|
+
if (cmdDoc.length > 0) {
|
|
143
|
+
this.writeTextWithNewLine(docFile, `${cmdDoc}\n`);
|
|
144
|
+
}
|
|
140
145
|
// get example
|
|
141
146
|
const examples = command.getExamples();
|
|
142
147
|
let example = '';
|
|
@@ -48,10 +48,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
48
48
|
const chalk_1 = __importDefault(require("chalk"));
|
|
49
49
|
const string_width_1 = __importDefault(require("string-width"));
|
|
50
50
|
const core_1 = require("@memlab/core");
|
|
51
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
51
52
|
const CommandOrder_1 = __importDefault(require("./lib/CommandOrder"));
|
|
52
53
|
const BaseCommand_1 = __importStar(require("../../BaseCommand"));
|
|
53
54
|
const UniversalOptions_1 = __importDefault(require("../../options/lib/UniversalOptions"));
|
|
54
|
-
const
|
|
55
|
+
const CLIUtils_1 = require("../../lib/CLIUtils");
|
|
55
56
|
class HelperCommand extends BaseCommand_1.default {
|
|
56
57
|
constructor() {
|
|
57
58
|
super(...arguments);
|
|
@@ -137,7 +138,7 @@ class HelperCommand extends BaseCommand_1.default {
|
|
|
137
138
|
if (options.length === 0) {
|
|
138
139
|
return '';
|
|
139
140
|
}
|
|
140
|
-
const width = Math.min(
|
|
141
|
+
const width = Math.min(CLIUtils_1.READABLE_CMD_FLAG_WIDTH, process.stdout.columns);
|
|
141
142
|
let summary = '';
|
|
142
143
|
let curLine = chalk_1.default.bold(`${indent}Options:`);
|
|
143
144
|
for (const option of options) {
|
|
@@ -177,25 +178,21 @@ class HelperCommand extends BaseCommand_1.default {
|
|
|
177
178
|
}
|
|
178
179
|
formatOptionText(optionText, indent, headerLength) {
|
|
179
180
|
const header = chalk_1.default.green(optionText.header);
|
|
180
|
-
const prefix =
|
|
181
|
+
const prefix = (0, CLIUtils_1.getBlankSpaceString)(headerLength - optionText.header.length);
|
|
181
182
|
const headerString = `${indent}${prefix}${header} `;
|
|
182
183
|
const headerStringWidth = (0, string_width_1.default)(headerString);
|
|
183
|
-
const maxWidth = Math.min(process.stdout.columns,
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
descString += core_1.utils.repeat(' ', headerStringWidth);
|
|
190
|
-
descString += descStringRemain.substring(0, descMaxWidth);
|
|
191
|
-
descStringRemain = descStringRemain.substring(descMaxWidth);
|
|
192
|
-
}
|
|
193
|
-
return `${headerString}${descString}`;
|
|
184
|
+
const maxWidth = Math.min(process.stdout.columns, CLIUtils_1.READABLE_TEXT_WIDTH);
|
|
185
|
+
const descString = (0, CLIUtils_1.alignTextInBlock)(optionText.desc, {
|
|
186
|
+
leftIndent: headerStringWidth,
|
|
187
|
+
lineLength: maxWidth,
|
|
188
|
+
});
|
|
189
|
+
return `${headerString}${descString.substring(headerStringWidth)}`;
|
|
194
190
|
}
|
|
195
191
|
printCommand(command, extraIndent = '', printOptions = false) {
|
|
196
192
|
const indent = ' ' + extraIndent;
|
|
197
193
|
const name = command.getFullCommand();
|
|
198
|
-
const desc = core_1.utils.upperCaseFirstCharacter(command.getDescription());
|
|
194
|
+
const desc = core_1.utils.upperCaseFirstCharacter(command.getDescription().trim());
|
|
195
|
+
const cmdDoc = command.getDocumenation().trim();
|
|
199
196
|
// get example
|
|
200
197
|
const examples = command.getExamples();
|
|
201
198
|
let example = '';
|
|
@@ -205,6 +202,12 @@ class HelperCommand extends BaseCommand_1.default {
|
|
|
205
202
|
const cmd = chalk_1.default.green(`memlab ${name}${example}`);
|
|
206
203
|
let msg = `${indent}${cmd}`;
|
|
207
204
|
msg += `\n${indent}${desc}`;
|
|
205
|
+
if (cmdDoc.length > 0) {
|
|
206
|
+
const cmdDocBlock = (0, CLIUtils_1.alignTextInBlock)(cmdDoc, {
|
|
207
|
+
leftIndent: indent.length + 2,
|
|
208
|
+
});
|
|
209
|
+
msg += `\n\n${chalk_1.default.grey(cmdDocBlock)}`;
|
|
210
|
+
}
|
|
208
211
|
core_1.info.topLevel(msg);
|
|
209
212
|
// print options info
|
|
210
213
|
if (printOptions) {
|
|
@@ -0,0 +1,22 @@
|
|
|
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 web_perf_infra
|
|
9
|
+
*/
|
|
10
|
+
import type { ParsedArgs } from 'minimist';
|
|
11
|
+
import type { AnyRecord } from '@memlab/core';
|
|
12
|
+
export declare type BlockTextOption = {
|
|
13
|
+
leftIndent?: number;
|
|
14
|
+
lineLength?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare const READABLE_CMD_FLAG_WIDTH = 70;
|
|
17
|
+
export declare const READABLE_TEXT_WIDTH = 150;
|
|
18
|
+
export declare function filterAndGetUndefinedArgs(cliArgs: ParsedArgs): AnyRecord;
|
|
19
|
+
export declare function argsToString(args: AnyRecord): string;
|
|
20
|
+
export declare function getBlankSpaceString(length: number): string;
|
|
21
|
+
export declare function alignTextInBlock(text: string, options: BlockTextOption): string;
|
|
22
|
+
//# sourceMappingURL=CLIUtils.d.ts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
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
|
+
exports.alignTextInBlock = exports.getBlankSpaceString = exports.argsToString = exports.filterAndGetUndefinedArgs = exports.READABLE_TEXT_WIDTH = exports.READABLE_CMD_FLAG_WIDTH = void 0;
|
|
7
|
+
const string_width_1 = __importDefault(require("string-width"));
|
|
8
|
+
const core_1 = require("@memlab/core");
|
|
9
|
+
const OptionConstant_1 = __importDefault(require("../options/lib/OptionConstant"));
|
|
10
|
+
const breakableSymbolOnRight = new Set([
|
|
11
|
+
' ',
|
|
12
|
+
'\t',
|
|
13
|
+
',',
|
|
14
|
+
'.',
|
|
15
|
+
':',
|
|
16
|
+
';',
|
|
17
|
+
'!',
|
|
18
|
+
'?',
|
|
19
|
+
')',
|
|
20
|
+
']',
|
|
21
|
+
'}',
|
|
22
|
+
'>',
|
|
23
|
+
]);
|
|
24
|
+
const breakableSymbolOnLeft = new Set([' ', '\t', '(', '[', '{', '<']);
|
|
25
|
+
exports.READABLE_CMD_FLAG_WIDTH = 70;
|
|
26
|
+
exports.READABLE_TEXT_WIDTH = 150;
|
|
27
|
+
function filterAndGetUndefinedArgs(cliArgs) {
|
|
28
|
+
const ret = Object.create(null);
|
|
29
|
+
const memlabFBOptionNames = new Set(Object.values(Object.assign({}, OptionConstant_1.default.optionNames)));
|
|
30
|
+
for (const optionName of Object.keys(cliArgs)) {
|
|
31
|
+
if (optionName === '_') {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (memlabFBOptionNames.has(optionName)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
ret[optionName] = cliArgs[optionName];
|
|
38
|
+
}
|
|
39
|
+
return ret;
|
|
40
|
+
}
|
|
41
|
+
exports.filterAndGetUndefinedArgs = filterAndGetUndefinedArgs;
|
|
42
|
+
function argsToString(args) {
|
|
43
|
+
let ret = '';
|
|
44
|
+
for (const optionName of Object.keys(args)) {
|
|
45
|
+
if (optionName === '_') {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const value = args[optionName];
|
|
49
|
+
if (value === true) {
|
|
50
|
+
ret += `--${optionName} `;
|
|
51
|
+
}
|
|
52
|
+
else if (Array.isArray(value)) {
|
|
53
|
+
value.forEach(v => {
|
|
54
|
+
ret += `--${optionName}=${v} `;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
ret += `--${optionName}=${value} `;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return ret.trim();
|
|
62
|
+
}
|
|
63
|
+
exports.argsToString = argsToString;
|
|
64
|
+
function getBlankSpaceString(length) {
|
|
65
|
+
let ret = '';
|
|
66
|
+
for (let i = 0; i < length; ++i) {
|
|
67
|
+
ret += ' ';
|
|
68
|
+
}
|
|
69
|
+
return ret;
|
|
70
|
+
}
|
|
71
|
+
exports.getBlankSpaceString = getBlankSpaceString;
|
|
72
|
+
function alignTextInBlock(text, options) {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
const indent = (_a = options.leftIndent) !== null && _a !== void 0 ? _a : 0;
|
|
75
|
+
const maxLineWidth = Math.min(exports.READABLE_TEXT_WIDTH, (_b = options.lineLength) !== null && _b !== void 0 ? _b : process.stdout.columns);
|
|
76
|
+
if (indent < 0 || maxLineWidth <= 0 || indent >= maxLineWidth) {
|
|
77
|
+
throw core_1.utils.haltOrThrow('invalid indent or maximum line width');
|
|
78
|
+
}
|
|
79
|
+
const indentString = getBlankSpaceString(indent);
|
|
80
|
+
const inputLines = text.split('\n');
|
|
81
|
+
const outputLines = [];
|
|
82
|
+
while (inputLines.length > 0) {
|
|
83
|
+
const line = inputLines.shift();
|
|
84
|
+
// if the current line can fit in cmd row
|
|
85
|
+
if ((0, string_width_1.default)(indentString + line) <= maxLineWidth) {
|
|
86
|
+
outputLines.push(indentString + line);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// otherwise split the current line
|
|
90
|
+
const intendedSplitPoint = maxLineWidth - indent;
|
|
91
|
+
const splitLines = splitIntoReadableSubstrings(line, intendedSplitPoint);
|
|
92
|
+
const [firstLine, restLine] = splitLines;
|
|
93
|
+
outputLines.push(indentString + firstLine);
|
|
94
|
+
inputLines.unshift(restLine);
|
|
95
|
+
}
|
|
96
|
+
return outputLines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
exports.alignTextInBlock = alignTextInBlock;
|
|
99
|
+
function splitIntoReadableSubstrings(text, intendedSplitPoint) {
|
|
100
|
+
if (intendedSplitPoint >= text.length) {
|
|
101
|
+
return [text];
|
|
102
|
+
}
|
|
103
|
+
let splitPoint = intendedSplitPoint;
|
|
104
|
+
while (splitPoint > 0) {
|
|
105
|
+
const ch = text[splitPoint];
|
|
106
|
+
if (breakableSymbolOnLeft.has(ch)) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (splitPoint - 1 > 0 &&
|
|
110
|
+
breakableSymbolOnRight.has(text[splitPoint - 1])) {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
--splitPoint;
|
|
114
|
+
}
|
|
115
|
+
if (splitPoint <= 0) {
|
|
116
|
+
splitPoint = intendedSplitPoint;
|
|
117
|
+
}
|
|
118
|
+
// if the second line starts with a ' ',
|
|
119
|
+
// skip the empty space
|
|
120
|
+
const firstLine = text.substring(0, splitPoint);
|
|
121
|
+
let secondLine = text.substring(splitPoint);
|
|
122
|
+
if (secondLine.startsWith(' ')) {
|
|
123
|
+
secondLine = secondLine.substring(1);
|
|
124
|
+
}
|
|
125
|
+
if (secondLine.length === 0) {
|
|
126
|
+
return [firstLine];
|
|
127
|
+
}
|
|
128
|
+
return [firstLine, secondLine];
|
|
129
|
+
}
|
|
@@ -13,6 +13,7 @@ import { BaseOption } from '@memlab/core';
|
|
|
13
13
|
export default class MLClusteringOption extends BaseOption {
|
|
14
14
|
getOptionName(): string;
|
|
15
15
|
getDescription(): string;
|
|
16
|
+
static hasOptionSet(args: ParsedArgs): boolean;
|
|
16
17
|
parse(config: MemLabConfig, args: ParsedArgs): Promise<void>;
|
|
17
18
|
}
|
|
18
19
|
//# sourceMappingURL=MLClusteringOption.d.ts.map
|
|
@@ -30,6 +30,10 @@ class MLClusteringOption extends core_1.BaseOption {
|
|
|
30
30
|
getDescription() {
|
|
31
31
|
return 'use machine learning algorithms for clustering leak traces (by default, traces are clustered by heuristics)';
|
|
32
32
|
}
|
|
33
|
+
static hasOptionSet(args) {
|
|
34
|
+
const name = OptionConstant_1.default.optionNames.ML_CLUSTERING;
|
|
35
|
+
return args[name] != null;
|
|
36
|
+
}
|
|
33
37
|
parse(config, args) {
|
|
34
38
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
39
|
const name = this.getOptionName();
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
10
|
import type { ParsedArgs } from 'minimist';
|
|
11
|
-
import type { AnyRecord, MemLabConfig } from '@memlab/core';
|
|
11
|
+
import type { AnyRecord, MemLabConfig, Optional } from '@memlab/core';
|
|
12
12
|
import { BaseOption } from '@memlab/core';
|
|
13
13
|
export default class NumberOfRunsOption extends BaseOption {
|
|
14
|
-
|
|
14
|
+
private defaultRunNumber;
|
|
15
|
+
constructor(runNumber?: number);
|
|
15
16
|
getOptionName(): string;
|
|
16
17
|
getDescription(): string;
|
|
17
18
|
getExampleValues(): string[];
|
|
19
|
+
static getParsedOption(configFromOptions: Optional<AnyRecord>): number;
|
|
18
20
|
parse(config: MemLabConfig, args: ParsedArgs): Promise<AnyRecord>;
|
|
19
21
|
}
|
|
20
22
|
//# sourceMappingURL=NumberOfRunsOption.d.ts.map
|
|
@@ -23,7 +23,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
const core_1 = require("@memlab/core");
|
|
25
25
|
const OptionConstant_1 = __importDefault(require("./lib/OptionConstant"));
|
|
26
|
+
const DEFAULT_NUM_RUNS = 10;
|
|
26
27
|
class NumberOfRunsOption extends core_1.BaseOption {
|
|
28
|
+
constructor(runNumber = DEFAULT_NUM_RUNS) {
|
|
29
|
+
super();
|
|
30
|
+
this.defaultRunNumber = DEFAULT_NUM_RUNS;
|
|
31
|
+
this.defaultRunNumber = runNumber;
|
|
32
|
+
}
|
|
27
33
|
getOptionName() {
|
|
28
34
|
return OptionConstant_1.default.optionNames.RUN_NUM;
|
|
29
35
|
}
|
|
@@ -33,16 +39,18 @@ class NumberOfRunsOption extends core_1.BaseOption {
|
|
|
33
39
|
getExampleValues() {
|
|
34
40
|
return ['5'];
|
|
35
41
|
}
|
|
42
|
+
static getParsedOption(configFromOptions) {
|
|
43
|
+
const { numOfRuns } = configFromOptions !== null && configFromOptions !== void 0 ? configFromOptions : {};
|
|
44
|
+
const n = parseInt(`${numOfRuns}`, 10);
|
|
45
|
+
return isNaN(n) ? DEFAULT_NUM_RUNS : n;
|
|
46
|
+
}
|
|
36
47
|
parse(config, args) {
|
|
37
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
49
|
const ret = Object.create(null);
|
|
39
50
|
const name = this.getOptionName();
|
|
40
|
-
ret.numOfRuns = args[name]
|
|
41
|
-
? args[name] | 0
|
|
42
|
-
: NumberOfRunsOption.DEFAULT_NUM_RUNS;
|
|
51
|
+
ret.numOfRuns = args[name] != null ? args[name] | 0 : this.defaultRunNumber;
|
|
43
52
|
return ret;
|
|
44
53
|
});
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
exports.default = NumberOfRunsOption;
|
|
48
|
-
NumberOfRunsOption.DEFAULT_NUM_RUNS = 10;
|
|
@@ -13,8 +13,9 @@ import { BaseOption } from '@memlab/core';
|
|
|
13
13
|
export default class SetControlWorkDirOption extends BaseOption {
|
|
14
14
|
getOptionName(): string;
|
|
15
15
|
getDescription(): string;
|
|
16
|
+
protected extractAndCheckWorkDirs(args: ParsedArgs): string[];
|
|
16
17
|
parse(config: MemLabConfig, args: ParsedArgs): Promise<{
|
|
17
|
-
|
|
18
|
+
controlWorkDirs?: string[];
|
|
18
19
|
}>;
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=SetControlWorkDirOption.d.ts.map
|
|
@@ -21,6 +21,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
25
|
const core_1 = require("@memlab/core");
|
|
25
26
|
const OptionConstant_1 = __importDefault(require("../lib/OptionConstant"));
|
|
26
27
|
class SetControlWorkDirOption extends core_1.BaseOption {
|
|
@@ -30,14 +31,32 @@ class SetControlWorkDirOption extends core_1.BaseOption {
|
|
|
30
31
|
getDescription() {
|
|
31
32
|
return 'set the working directory of the control run';
|
|
32
33
|
}
|
|
34
|
+
extractAndCheckWorkDirs(args) {
|
|
35
|
+
let dirs = [];
|
|
36
|
+
const name = this.getOptionName();
|
|
37
|
+
const flagValue = args[name];
|
|
38
|
+
if (!flagValue) {
|
|
39
|
+
return dirs;
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(flagValue)) {
|
|
42
|
+
dirs = flagValue;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
dirs = [flagValue];
|
|
46
|
+
}
|
|
47
|
+
for (const dir of dirs) {
|
|
48
|
+
if (fs_1.default.existsSync(dir)) {
|
|
49
|
+
core_1.fileManager.createDefaultVisitOrderMetaFile({
|
|
50
|
+
workDir: dir,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return dirs;
|
|
55
|
+
}
|
|
33
56
|
parse(config, args) {
|
|
34
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
if (args[name]) {
|
|
38
|
-
ret.controlWorkDir = args[name];
|
|
39
|
-
}
|
|
40
|
-
return ret;
|
|
58
|
+
const dirs = this.extractAndCheckWorkDirs(args);
|
|
59
|
+
return { controlWorkDirs: dirs };
|
|
41
60
|
});
|
|
42
61
|
}
|
|
43
62
|
}
|
|
@@ -21,6 +21,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
25
|
const core_1 = require("@memlab/core");
|
|
25
26
|
const OptionConstant_1 = __importDefault(require("../lib/OptionConstant"));
|
|
26
27
|
class SetTreatmentWorkDirOption extends core_1.BaseOption {
|
|
@@ -36,6 +37,11 @@ class SetTreatmentWorkDirOption extends core_1.BaseOption {
|
|
|
36
37
|
const ret = {};
|
|
37
38
|
if (args[name]) {
|
|
38
39
|
ret.treatmentWorkDir = args[name];
|
|
40
|
+
if (fs_1.default.existsSync(ret.treatmentWorkDir)) {
|
|
41
|
+
core_1.fileManager.createDefaultVisitOrderMetaFile({
|
|
42
|
+
workDir: ret.treatmentWorkDir,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
return ret;
|
|
41
47
|
});
|
|
@@ -23,6 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
const core_1 = require("@memlab/core");
|
|
25
25
|
const OptionConstant_1 = __importDefault(require("../lib/OptionConstant"));
|
|
26
|
+
const OversizeThresholdOption_1 = __importDefault(require("./OversizeThresholdOption"));
|
|
26
27
|
class TraceAllObjectsOption extends core_1.BaseOption {
|
|
27
28
|
getOptionName() {
|
|
28
29
|
return OptionConstant_1.default.optionNames.TRACE_ALL_OBJECTS;
|
|
@@ -32,8 +33,13 @@ class TraceAllObjectsOption extends core_1.BaseOption {
|
|
|
32
33
|
}
|
|
33
34
|
parse(config, args) {
|
|
34
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
if (args[this.getOptionName()]) {
|
|
36
|
-
|
|
36
|
+
if (!args[this.getOptionName()]) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
config.oversizeObjectAsLeak = true;
|
|
40
|
+
const overSizeOptionName = new OversizeThresholdOption_1.default().getOptionName();
|
|
41
|
+
// over size option will set the oversize threshold
|
|
42
|
+
if (!args[overSizeOptionName]) {
|
|
37
43
|
config.oversizeThreshold = 0;
|
|
38
44
|
}
|
|
39
45
|
});
|