@memlab/core 1.1.20 → 1.1.21

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 (41) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +4 -1
  3. package/dist/lib/Config.d.ts +2 -0
  4. package/dist/lib/Config.js +9 -0
  5. package/dist/lib/FileManager.d.ts +3 -0
  6. package/dist/lib/FileManager.js +10 -1
  7. package/dist/lib/HeapAnalyzer.d.ts +5 -1
  8. package/dist/lib/HeapAnalyzer.js +33 -21
  9. package/dist/lib/RunInfoUtils.d.ts +39 -0
  10. package/dist/lib/RunInfoUtils.js +86 -0
  11. package/dist/lib/Types.d.ts +7 -2
  12. package/dist/lib/Utils.d.ts +25 -19
  13. package/dist/lib/Utils.js +90 -148
  14. package/dist/lib/charts/MemoryBarChart.d.ts +1 -0
  15. package/dist/lib/charts/MemoryBarChart.js +18 -3
  16. package/dist/lib/trace-filters/BaseTraceFilter.rule.d.ts +29 -0
  17. package/dist/lib/trace-filters/BaseTraceFilter.rule.js +22 -0
  18. package/dist/lib/trace-filters/LeakTraceFilter.d.ts +20 -0
  19. package/dist/lib/trace-filters/LeakTraceFilter.js +37 -0
  20. package/dist/lib/trace-filters/TraceFilterRuleList.d.ts +13 -0
  21. package/dist/lib/trace-filters/TraceFilterRuleList.js +33 -0
  22. package/dist/lib/trace-filters/rules/FilterAttachedDOMToDetachedDOMTrace.rule.d.ts +15 -0
  23. package/dist/lib/trace-filters/rules/FilterAttachedDOMToDetachedDOMTrace.rule.js +55 -0
  24. package/dist/lib/trace-filters/rules/FilterDOMNodeChainTrace.rule.d.ts +15 -0
  25. package/dist/lib/trace-filters/rules/FilterDOMNodeChainTrace.rule.js +41 -0
  26. package/dist/lib/trace-filters/rules/FilterHermesTrace.rule.d.ts +15 -0
  27. package/dist/lib/trace-filters/rules/FilterHermesTrace.rule.js +29 -0
  28. package/dist/lib/trace-filters/rules/FilterInternalNodeTrace.rule.d.ts +15 -0
  29. package/dist/lib/trace-filters/rules/FilterInternalNodeTrace.rule.js +57 -0
  30. package/dist/lib/trace-filters/rules/FilterPendingActivitiesTrace.rule.d.ts +15 -0
  31. package/dist/lib/trace-filters/rules/FilterPendingActivitiesTrace.rule.js +62 -0
  32. package/dist/lib/trace-filters/rules/FilterShadowRootTrace.rule.d.ts +15 -0
  33. package/dist/lib/trace-filters/rules/FilterShadowRootTrace.rule.js +44 -0
  34. package/dist/lib/trace-filters/rules/FilterStyleEngineTrace.rule.d.ts +15 -0
  35. package/dist/lib/trace-filters/rules/FilterStyleEngineTrace.rule.js +49 -0
  36. package/dist/logger/LeakClusterLogger.js +1 -0
  37. package/dist/paths/TraceFinder.js +16 -2
  38. package/dist/trace-cluster/TraceBucket.d.ts +1 -1
  39. package/dist/trace-cluster/TraceBucket.js +7 -3
  40. package/dist/trace-cluster/strategies/TraceSimilarityStrategy.js +1 -0
  41. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -26,6 +26,8 @@ export { default as utils } from './lib/Utils';
26
26
  /** @internal */
27
27
  export { default as fileManager } from './lib/FileManager';
28
28
  /** @internal */
29
+ export { default as runInfoUtils } from './lib/RunInfoUtils';
30
+ /** @internal */
29
31
  export * from './lib/FileManager';
30
32
  /** @internal */
31
33
  export { default as serializer } from './lib/Serializer';
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.TraceFinder = exports.MultiIterationSeqClustering = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.memoryBarChart = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
38
+ exports.TraceFinder = exports.MultiIterationSeqClustering = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.memoryBarChart = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.runInfoUtils = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
39
39
  const path_1 = __importDefault(require("path"));
40
40
  const PackageInfoLoader_1 = require("./lib/PackageInfoLoader");
41
41
  __exportStar(require("./lib/Types"), exports);
@@ -67,6 +67,9 @@ Object.defineProperty(exports, "utils", { enumerable: true, get: function () { r
67
67
  var FileManager_1 = require("./lib/FileManager");
68
68
  Object.defineProperty(exports, "fileManager", { enumerable: true, get: function () { return __importDefault(FileManager_1).default; } });
69
69
  /** @internal */
70
+ var RunInfoUtils_1 = require("./lib/RunInfoUtils");
71
+ Object.defineProperty(exports, "runInfoUtils", { enumerable: true, get: function () { return __importDefault(RunInfoUtils_1).default; } });
72
+ /** @internal */
70
73
  __exportStar(require("./lib/FileManager"), exports);
71
74
  /** @internal */
72
75
  var Serializer_1 = require("./lib/Serializer");
@@ -99,6 +99,7 @@ export declare class MemLabConfig {
99
99
  dataBuilderDataDir: string;
100
100
  unclassifiedClusterDir: string;
101
101
  externalCookiesFile: Optional<string>;
102
+ extraRunInfoMap: Map<string, string>;
102
103
  heapConfig: Optional<IHeapConfig>;
103
104
  puppeteerConfig: LaunchOptions & BrowserLaunchArgumentOptions & BrowserConnectOptions;
104
105
  openDevtoolsConsole: boolean;
@@ -225,6 +226,7 @@ export declare class MemLabConfig {
225
226
  setDevice(deviceName: string, options?: {
226
227
  manualOverride?: boolean;
227
228
  }): void;
229
+ setRunInfo(key: string, value: string): void;
228
230
  private removeFromSet;
229
231
  private addToSet;
230
232
  enableXvfb(display: string): void;
@@ -176,6 +176,12 @@ class MemLabConfig {
176
176
  // if true, split dataset into trunks
177
177
  // with random order for sequential clustering
178
178
  this.seqClusteringIsRandomChunks = false;
179
+ // extra E2E run info (other than the fields defined in
180
+ // RunMetaInfo like app, interaction, browserInfo).
181
+ // Information saved in this map will be
182
+ // auto-serialized to run-meta.json when the file is saved
183
+ // and auto-deserialized from run-meta.json when the file is loaded
184
+ this.extraRunInfoMap = new Map();
179
185
  }
180
186
  // initialize configurable parameters
181
187
  init(options = {}) {
@@ -507,6 +513,9 @@ class MemLabConfig {
507
513
  this.puppeteerConfig.defaultViewport = null;
508
514
  this.defaultUserAgent = null;
509
515
  }
516
+ setRunInfo(key, value) {
517
+ this.extraRunInfoMap.set(key, value);
518
+ }
510
519
  removeFromSet(set, list) {
511
520
  for (const v of list) {
512
521
  set.delete(v);
@@ -10,6 +10,8 @@
10
10
  import type { MemLabConfig } from './Config';
11
11
  import type { AnyValue, FileOption } from './Types';
12
12
  /** @internal */
13
+ export declare function joinAndProcessDir(options: FileOption, ...args: AnyValue[]): string;
14
+ /** @internal */
13
15
  export declare class FileManager {
14
16
  private memlabConfigCache;
15
17
  getDefaultWorkDir(): string;
@@ -75,6 +77,7 @@ export declare class FileManager {
75
77
  rmWorkDir(options?: FileOption): void;
76
78
  isWithinInternalDirectory(filePath: string): boolean;
77
79
  createDefaultVisitOrderMetaFile(options?: FileOption): void;
80
+ createDefaultVisitOrderMetaFileWithSingleSnapshot(options: FileOption | undefined, snapshotFile: string): void;
78
81
  initDirs(config: MemLabConfig, options?: FileOption): void;
79
82
  }
80
83
  declare const _default: FileManager;
@@ -12,13 +12,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.FileManager = void 0;
15
+ exports.FileManager = exports.joinAndProcessDir = void 0;
16
16
  const fs_extra_1 = __importDefault(require("fs-extra"));
17
17
  const os_1 = __importDefault(require("os"));
18
18
  const path_1 = __importDefault(require("path"));
19
19
  const Console_1 = __importDefault(require("./Console"));
20
20
  const Constant_1 = __importDefault(require("./Constant"));
21
21
  const Utils_1 = __importDefault(require("./Utils"));
22
+ /** @internal */
22
23
  function joinAndProcessDir(options, ...args) {
23
24
  const filepath = path_1.default.join(...args);
24
25
  if (!fs_extra_1.default.existsSync(filepath)) {
@@ -34,6 +35,7 @@ function joinAndProcessDir(options, ...args) {
34
35
  }
35
36
  return filepath;
36
37
  }
38
+ exports.joinAndProcessDir = joinAndProcessDir;
37
39
  /** @internal */
38
40
  class FileManager {
39
41
  constructor() {
@@ -310,6 +312,9 @@ class FileManager {
310
312
  }
311
313
  }
312
314
  isDirectory(file) {
315
+ if (!fs_extra_1.default.existsSync(file)) {
316
+ return false;
317
+ }
313
318
  const stats = fs_extra_1.default.statSync(file);
314
319
  return stats.isDirectory();
315
320
  }
@@ -356,6 +361,10 @@ class FileManager {
356
361
  }
357
362
  // If there is at least one snapshot, create a snap-seq.json file.
358
363
  // First, get the meta file for leak detection in a single heap snapshot
364
+ this.createDefaultVisitOrderMetaFileWithSingleSnapshot(options, snapshotFile);
365
+ }
366
+ createDefaultVisitOrderMetaFileWithSingleSnapshot(options = FileManager.defaultFileOption, snapshotFile) {
367
+ const snapshotSeqMetaFile = this.getSnapshotSequenceMetaFile(options);
359
368
  const codeDataDir = this.getCodeDataDir();
360
369
  const singleSnapshotMetaFile = path_1.default.join(codeDataDir, 'visit-order-single-snapshot.json');
361
370
  const visitOrder = JSON.parse(fs_extra_1.default.readFileSync(singleSnapshotMetaFile, 'UTF-8'));
@@ -16,6 +16,10 @@ declare type DiffSnapshotsOptions = {
16
16
  declare type WorkDirOptions = {
17
17
  workDir?: string;
18
18
  };
19
+ declare type GetTraceOptions = {
20
+ workDir?: string;
21
+ printConsoleOnly?: boolean;
22
+ };
19
23
  declare class MemoryAnalyst {
20
24
  checkLeak(): Promise<ISerializedInfo[]>;
21
25
  diffLeakByWorkDir(options: DiffLeakOptions): Promise<ISerializedInfo[]>;
@@ -50,7 +54,7 @@ declare class MemoryAnalyst {
50
54
  serializeClusterUpdate(clusters: TraceCluster[], options?: {
51
55
  reclusterOnly?: boolean;
52
56
  }): Promise<void>;
53
- dumpPathByNodeId(leakedIdSet: HeapNodeIdSet, snapshot: IHeapSnapshot, nodeIdsInSnapshots: Array<HeapNodeIdSet>, id: number, pathLoaderFile: string, summaryFile: string, options?: WorkDirOptions): void;
57
+ dumpPathByNodeId(leakedIdSet: HeapNodeIdSet, snapshot: IHeapSnapshot, nodeIdsInSnapshots: Array<HeapNodeIdSet>, id: number, pathLoaderFile: string, summaryFile: string, options?: GetTraceOptions): void;
54
58
  }
55
59
  declare const _default: MemoryAnalyst;
56
60
  export default _default;
@@ -34,6 +34,7 @@ const TraceFinder_1 = __importDefault(require("../paths/TraceFinder"));
34
34
  const TraceBucket_1 = __importDefault(require("../trace-cluster/TraceBucket"));
35
35
  const LeakObjectFilter_1 = require("./leak-filters/LeakObjectFilter");
36
36
  const MLTraceSimilarityStrategy_1 = __importDefault(require("../trace-cluster/strategies/MLTraceSimilarityStrategy"));
37
+ const LeakTraceFilter_1 = require("./trace-filters/LeakTraceFilter");
37
38
  class MemoryAnalyst {
38
39
  checkLeak() {
39
40
  return __awaiter(this, void 0, void 0, function* () {
@@ -44,14 +45,14 @@ class MemoryAnalyst {
44
45
  }
45
46
  diffLeakByWorkDir(options) {
46
47
  return __awaiter(this, void 0, void 0, function* () {
47
- const controlSnapshotDir = FileManager_1.default.getCurDataDir({
48
- workDir: options.controlWorkDir,
49
- });
48
+ const controlSnapshotDirs = options.controlWorkDirs.map(controlWorkDir => FileManager_1.default.getCurDataDir({
49
+ workDir: controlWorkDir,
50
+ }));
50
51
  const treatmentSnapshotDir = FileManager_1.default.getCurDataDir({
51
52
  workDir: options.treatmentWorkDir,
52
53
  });
53
54
  // check control working dir
54
- Utils_1.default.checkSnapshots({ snapshotDir: controlSnapshotDir });
55
+ controlSnapshotDirs.forEach(controlSnapshotDir => Utils_1.default.checkSnapshots({ snapshotDir: controlSnapshotDir }));
55
56
  // check treatment working dir
56
57
  Utils_1.default.checkSnapshots({ snapshotDir: treatmentSnapshotDir });
57
58
  // display control and treatment memory
@@ -63,31 +64,37 @@ class MemoryAnalyst {
63
64
  diffMemoryLeakTraces(options) {
64
65
  return __awaiter(this, void 0, void 0, function* () {
65
66
  Config_1.default.dumpNodeInfo = false;
66
- // diff snapshots and get control raw paths
67
- let snapshotDiff = yield this.diffSnapshots({
68
- loadAllSnapshots: true,
69
- workDir: options.controlWorkDir,
70
- });
71
- const controlLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.controlWorkDir });
72
- const controlSnapshot = snapshotDiff.snapshot;
67
+ // diff snapshots from control dirs and get control raw paths array
68
+ const controlSnapshots = [];
69
+ const leakPathsFromControlRuns = [];
70
+ for (const controlWorkDir of options.controlWorkDirs) {
71
+ const snapshotDiff = yield this.diffSnapshots({
72
+ loadAllSnapshots: true,
73
+ workDir: controlWorkDir,
74
+ });
75
+ leakPathsFromControlRuns.push(this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: controlWorkDir }));
76
+ controlSnapshots.push(snapshotDiff.snapshot);
77
+ }
73
78
  // diff snapshots and get treatment raw paths
74
- snapshotDiff = yield this.diffSnapshots({
79
+ const snapshotDiff = yield this.diffSnapshots({
75
80
  loadAllSnapshots: true,
76
81
  workDir: options.treatmentWorkDir,
77
82
  });
78
- const treatmentLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.controlWorkDir });
83
+ const treatmentLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.treatmentWorkDir });
79
84
  const treatmentSnapshot = snapshotDiff.snapshot;
80
- Console_1.default.topLevel(`${controlLeakPaths.length} traces from control group`);
85
+ const controlPathCounts = JSON.stringify(leakPathsFromControlRuns.map(leakPaths => leakPaths.length));
86
+ Console_1.default.topLevel(`${controlPathCounts} traces from control group`);
81
87
  Console_1.default.topLevel(`${treatmentLeakPaths.length} traces from treatment group`);
82
- const result = TraceBucket_1.default.clusterControlTreatmentPaths(controlLeakPaths, controlSnapshot, treatmentLeakPaths, treatmentSnapshot, Utils_1.default.aggregateDominatorMetrics, {
88
+ const result = TraceBucket_1.default.clusterControlTreatmentPaths(leakPathsFromControlRuns, controlSnapshots, treatmentLeakPaths, treatmentSnapshot, Utils_1.default.aggregateDominatorMetrics, {
83
89
  strategy: Config_1.default.isMLClustering
84
90
  ? new MLTraceSimilarityStrategy_1.default()
85
91
  : undefined,
86
92
  });
87
93
  Console_1.default.midLevel(`MemLab found ${result.treatmentOnlyClusters.length} new leak(s) in the treatment group`);
88
94
  yield this.serializeClusterUpdate(result.treatmentOnlyClusters);
89
- // TODO (lgong): log leak traces
90
- return [];
95
+ // serialize JSON file with detailed leak trace information
96
+ const treatmentOnlyPaths = result.treatmentOnlyClusters.map(c => c.path);
97
+ return LeakTraceDetailsLogger_1.default.logTraces(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, snapshotDiff.listOfLeakedHeapNodeIdSet, treatmentOnlyPaths, Config_1.default.traceJsonOutDir);
91
98
  });
92
99
  }
93
100
  // find all unique pattern of leaks
@@ -124,7 +131,7 @@ class MemoryAnalyst {
124
131
  snapshotLeakedHeapNodeIdSet = snapshotDiff.leakedHeapNodeIdSet;
125
132
  snapshot = snapshotDiff.snapshot;
126
133
  }
127
- this.dumpPathByNodeId(snapshotLeakedHeapNodeIdSet, snapshot, nodeIdsInSnapshots, Config_1.default.focusFiberNodeId, Config_1.default.viewJsonFile, Config_1.default.singleReportSummary);
134
+ this.dumpPathByNodeId(snapshotLeakedHeapNodeIdSet, snapshot, nodeIdsInSnapshots, Config_1.default.focusFiberNodeId, Config_1.default.viewJsonFile, Config_1.default.singleReportSummary, { printConsoleOnly: true });
128
135
  });
129
136
  }
130
137
  shouldLoadCompleteSnapshot(tabsOrder, tab) {
@@ -348,6 +355,7 @@ class MemoryAnalyst {
348
355
  this.printHeapAndLeakInfo(leakedNodeIds, snapshot, options);
349
356
  // get all leaked objects
350
357
  this.filterLeakedObjects(leakedNodeIds, snapshot);
358
+ const leakTraceFilter = new LeakTraceFilter_1.LeakTraceFilter();
351
359
  const nodeIdInPaths = new Set();
352
360
  const paths = [];
353
361
  let numOfLeakedObjects = 0;
@@ -359,7 +367,8 @@ class MemoryAnalyst {
359
367
  }
360
368
  // BFS search for path from the leaked node to GC roots
361
369
  const p = finder.getPathToGCRoots(snapshot, node);
362
- if (!p || !Utils_1.default.isInterestingPath(p)) {
370
+ if (p == null ||
371
+ !leakTraceFilter.filter(p, { config: Config_1.default, leakedNodeIds, snapshot })) {
363
372
  return;
364
373
  }
365
374
  ++numOfLeakedObjects;
@@ -451,10 +460,13 @@ class MemoryAnalyst {
451
460
  return;
452
461
  }
453
462
  LeakTraceDetailsLogger_1.default.logTrace(leakedIdSet, snapshot, nodeIdsInSnapshots, path, pathLoaderFile);
454
- const tabsOrder = Utils_1.default.loadTabsOrder(FileManager_1.default.getSnapshotSequenceMetaFile(options));
455
- const interactionSummary = Serializer_1.default.summarizeTabsOrder(tabsOrder);
456
463
  let pathSummary = Serializer_1.default.summarizePath(path, nodeIdInPaths, snapshot, { color: true });
457
464
  Console_1.default.topLevel(pathSummary);
465
+ if (options.printConsoleOnly) {
466
+ return;
467
+ }
468
+ const tabsOrder = Utils_1.default.loadTabsOrder(FileManager_1.default.getSnapshotSequenceMetaFile(options));
469
+ const interactionSummary = Serializer_1.default.summarizeTabsOrder(tabsOrder);
458
470
  pathSummary = Serializer_1.default.summarizePath(path, nodeIdInPaths, snapshot);
459
471
  const summary = `Page Interaction: \n${interactionSummary}\n\n` +
460
472
  `Path from GC Root to Leaked Object:\n${pathSummary}`;
@@ -0,0 +1,39 @@
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 { Nullable, Optional, RunMetaInfo } from './Types';
11
+ export declare class RunMetaInfoManager {
12
+ getRunMetaFilePath(options?: {
13
+ workDir?: Optional<string>;
14
+ }): string;
15
+ saveRunMetaInfo(runMetaInfo: RunMetaInfo, options?: {
16
+ workDir?: Optional<string>;
17
+ extraRunInfo?: Map<string, string>;
18
+ }): string;
19
+ private loadRunMetaInfoFromFile;
20
+ loadRunMetaInfo(options?: {
21
+ metaFile?: Optional<string>;
22
+ workDir?: Optional<string>;
23
+ }): RunMetaInfo;
24
+ loadRunMetaInfoSilentFail(options?: {
25
+ metaFile?: Optional<string>;
26
+ workDir?: Optional<string>;
27
+ }): Nullable<RunMetaInfo>;
28
+ loadRunMetaExternalTemplate(): RunMetaInfo;
29
+ setConfigFromRunMeta(options?: {
30
+ workDir?: Optional<string>;
31
+ silentFail?: boolean;
32
+ }): void;
33
+ }
34
+ declare const runInfoUtils: {
35
+ runMetaInfoManager: RunMetaInfoManager;
36
+ };
37
+ /** @internal */
38
+ export default runInfoUtils;
39
+ //# sourceMappingURL=RunInfoUtils.d.ts.map
@@ -0,0 +1,86 @@
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.RunMetaInfoManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const BrowserInfo_1 = __importDefault(require("./BrowserInfo"));
9
+ const Config_1 = __importDefault(require("./Config"));
10
+ const Constant_1 = __importDefault(require("./Constant"));
11
+ const FileManager_1 = __importDefault(require("./FileManager"));
12
+ const Utils_1 = __importDefault(require("./Utils"));
13
+ const InternalValueSetter_1 = require("./InternalValueSetter");
14
+ class RunMetaInfoManager {
15
+ getRunMetaFilePath(options) {
16
+ if ((options === null || options === void 0 ? void 0 : options.workDir) != null) {
17
+ return FileManager_1.default.getRunMetaFile({ workDir: options.workDir });
18
+ }
19
+ if (Config_1.default.useExternalSnapshot) {
20
+ return Config_1.default.externalRunMetaFile;
21
+ }
22
+ if (Config_1.default.runMetaFile != null) {
23
+ return Config_1.default.runMetaFile;
24
+ }
25
+ return FileManager_1.default.getRunMetaFile();
26
+ }
27
+ saveRunMetaInfo(runMetaInfo, options) {
28
+ var _a;
29
+ const runMetaFile = this.getRunMetaFilePath(options);
30
+ const serializable = Object.assign(Object.assign({}, runMetaInfo), { extraInfo: Object.assign(Object.assign({}, Utils_1.default.mapToObject(Config_1.default.extraRunInfoMap)), Utils_1.default.mapToObject((_a = options === null || options === void 0 ? void 0 : options.extraRunInfo) !== null && _a !== void 0 ? _a : new Map())) });
31
+ fs_1.default.writeFileSync(runMetaFile, JSON.stringify(serializable, null, 2), 'UTF-8');
32
+ return runMetaFile;
33
+ }
34
+ loadRunMetaInfoFromFile(file) {
35
+ const content = fs_1.default.readFileSync(file, 'UTF-8');
36
+ const runMetaInfo = JSON.parse(content);
37
+ if (runMetaInfo && runMetaInfo.extraInfo) {
38
+ Config_1.default.extraRunInfoMap = Utils_1.default.objectToMap(runMetaInfo.extraInfo);
39
+ }
40
+ return runMetaInfo;
41
+ }
42
+ loadRunMetaInfo(options) {
43
+ const file = (options === null || options === void 0 ? void 0 : options.metaFile) || this.getRunMetaFilePath(options);
44
+ try {
45
+ return this.loadRunMetaInfoFromFile(file);
46
+ }
47
+ catch (_) {
48
+ throw Utils_1.default.haltOrThrow('Run info missing. Please make sure `memlab run` is complete.');
49
+ }
50
+ }
51
+ loadRunMetaInfoSilentFail(options) {
52
+ const file = (options === null || options === void 0 ? void 0 : options.metaFile) || this.getRunMetaFilePath(options);
53
+ try {
54
+ return this.loadRunMetaInfoFromFile(file);
55
+ }
56
+ catch (_) {
57
+ return null;
58
+ }
59
+ }
60
+ loadRunMetaExternalTemplate() {
61
+ const runMetaTemplateFile = FileManager_1.default.getRunMetaExternalTemplateFile();
62
+ return JSON.parse(fs_1.default.readFileSync(runMetaTemplateFile, 'UTF-8'));
63
+ }
64
+ setConfigFromRunMeta(options = {}) {
65
+ const meta = (options === null || options === void 0 ? void 0 : options.silentFail)
66
+ ? this.loadRunMetaInfoSilentFail(options)
67
+ : this.loadRunMetaInfo(options);
68
+ if (meta == null) {
69
+ return;
70
+ }
71
+ if ((meta === null || meta === void 0 ? void 0 : meta.app) == null || (meta === null || meta === void 0 ? void 0 : meta.interaction) == null) {
72
+ if (options === null || options === void 0 ? void 0 : options.silentFail) {
73
+ return;
74
+ }
75
+ throw Utils_1.default.haltOrThrow('No app or interaction infomation');
76
+ }
77
+ Config_1.default.targetApp = meta.app;
78
+ Config_1.default.targetTab = meta.interaction;
79
+ BrowserInfo_1.default.load(meta.browserInfo);
80
+ }
81
+ }
82
+ exports.RunMetaInfoManager = RunMetaInfoManager;
83
+ const runInfoUtils = { runMetaInfoManager: new RunMetaInfoManager() };
84
+ (0, InternalValueSetter_1.setInternalValue)(runInfoUtils, __filename, Constant_1.default.internalDir);
85
+ /** @internal */
86
+ exports.default = runInfoUtils;
@@ -23,6 +23,8 @@ export declare type Optional<T> = Nullable<T> | undefined;
23
23
  /** @internal */
24
24
  export declare type AnyRecord = Record<string, RecordValue>;
25
25
  /** @internal */
26
+ export declare type StringRecord = Record<string, string>;
27
+ /** @internal */
26
28
  export declare type AnyAyncFunction = (...args: AnyValue[]) => Promise<AnyValue>;
27
29
  /** @internal */
28
30
  export declare type AnyFunction = (...args: AnyValue[]) => AnyValue;
@@ -66,6 +68,7 @@ export declare type XvfbType = {
66
68
  export declare type ShellOptions = {
67
69
  dir?: Optional<string>;
68
70
  ignoreError?: Optional<boolean>;
71
+ throwError?: Optional<boolean>;
69
72
  disconnectStdio?: Optional<boolean>;
70
73
  };
71
74
  /** @internal */
@@ -942,6 +945,8 @@ export declare type RunMetaInfo = {
942
945
  * output data from the browser
943
946
  */
944
947
  browserInfo: IBrowserInfo;
948
+ /** @internal */
949
+ extraInfo?: StringRecord;
945
950
  };
946
951
  /**
947
952
  * A heap snapshot is generally a graph where graph nodes are JS heap objects
@@ -1924,12 +1929,12 @@ export interface IOveralLeakInfo extends Partial<IOveralHeapInfo> {
1924
1929
  }
1925
1930
  /** @internal */
1926
1931
  export declare type DiffLeakOptions = {
1927
- controlWorkDir: string;
1932
+ controlWorkDirs: string[];
1928
1933
  treatmentWorkDir: string;
1929
1934
  };
1930
1935
  /** @internal */
1931
1936
  export declare type PlotMemoryOptions = {
1932
- controlWorkDir?: string;
1937
+ controlWorkDirs?: string[];
1933
1938
  treatmentWorkDir?: string;
1934
1939
  workDir?: string;
1935
1940
  } & IMemoryAnalystOptions;
@@ -7,13 +7,15 @@
7
7
  * @format
8
8
  * @oncall web_perf_infra
9
9
  */
10
- import type { HaltOrThrowOptions, HeapNodeIdSet, ShellOptions } from './Types';
10
+ import type { HaltOrThrowOptions, HeapNodeIdSet, ShellOptions, StringRecord } from './Types';
11
11
  import type { Browser, Page } from 'puppeteer';
12
- import type { AnyAyncFunction, AnyOptions, E2EStepInfo, IHeapSnapshot, IHeapNode, IHeapEdge, IScenario, ILeakFilter, LeakTracePathItem, RunMetaInfo, RawHeapSnapshot, Nullable, Optional } from './Types';
12
+ import type { AnyAyncFunction, AnyOptions, E2EStepInfo, IHeapSnapshot, IHeapNode, IHeapEdge, IScenario, ILeakFilter, LeakTracePathItem, RawHeapSnapshot, Nullable, Optional } from './Types';
13
13
  declare function isHermesInternalObject(node: IHeapNode): boolean;
14
14
  declare function isStackTraceFrame(node: IHeapNode): boolean;
15
15
  declare function isFiberNode(node: Optional<IHeapNode>): boolean;
16
16
  declare function isDetachedFiberNode(node: IHeapNode): boolean;
17
+ declare function isDOMInternalNode(node: Optional<IHeapNode>): boolean;
18
+ declare function isGlobalHandlesNode(node: Optional<IHeapNode>): boolean;
17
19
  declare function isDetachedDOMNode(node: Optional<IHeapNode>, args?: AnyOptions): boolean;
18
20
  declare function isWeakMapEdge(edge: IHeapEdge): boolean;
19
21
  declare function isWeakMapEdgeToKey(edge: IHeapEdge): boolean;
@@ -23,6 +25,9 @@ declare function isFiberNodeDeletionsEdge(edge: IHeapEdge): boolean;
23
25
  declare function isBlinkRootNode(node: IHeapNode): boolean;
24
26
  declare function isPendingActivityNode(node: IHeapNode): boolean;
25
27
  declare function isDOMNodeIncomplete(node: IHeapNode): boolean;
28
+ declare function isXMLDocumentNode(node: IHeapNode): boolean;
29
+ declare function isHTMLDocumentNode(node: IHeapNode): boolean;
30
+ declare function isDOMTextNode(node: IHeapNode): boolean;
26
31
  declare function isRootNode(node: IHeapNode, opt?: AnyOptions): boolean;
27
32
  declare function isDirectPropEdge(edge: IHeapEdge): boolean;
28
33
  declare function isReturnEdge(edge: IHeapEdge): boolean;
@@ -64,12 +69,8 @@ declare function getBooleanNodeValue(node: IHeapNode): Nullable<boolean>;
64
69
  declare function getToNodeByEdge(node: Nullable<IHeapNode>, propName: string, propType?: string): Nullable<IHeapNode>;
65
70
  declare function extractHTMLElementNodeInfo(node: IHeapNode): string;
66
71
  declare function hasOnlyWeakReferrers(node: IHeapNode): boolean;
67
- declare function getRunMetaFilePath(): string;
68
- declare function loadRunMetaInfo(metaFile?: Optional<string>): RunMetaInfo;
69
- declare function loadTargetInfoFromRunMeta(): void;
70
72
  declare function getSnapshotSequenceFilePath(): string;
71
73
  declare function loadTabsOrder(metaFile?: Optional<string>): E2EStepInfo[];
72
- declare function isInterestingPath(p: LeakTracePathItem): boolean;
73
74
  declare function isObjectNode(node: IHeapNode): boolean;
74
75
  declare function isPlainJSObjectNode(node: IHeapNode): boolean;
75
76
  declare function pathHasDetachedHTMLNode(path: LeakTracePathItem): boolean;
@@ -129,14 +130,16 @@ declare function getRetainedSize(node: IHeapNode): number;
129
130
  declare function aggregateDominatorMetrics(ids: HeapNodeIdSet, snapshot: IHeapSnapshot, checkNodeCb: (node: IHeapNode) => boolean, nodeMetricsCb: (node: IHeapNode) => number): number;
130
131
  declare function getLeakTracePathLength(path: LeakTracePathItem): number;
131
132
  declare function getNumberAtPercentile(arr: number[], percentile: number): number;
133
+ declare function mapToObject(map: Map<string, string>): StringRecord;
134
+ declare function objectToMap(object: StringRecord): Map<string, string>;
132
135
  declare const _default: {
133
136
  aggregateDominatorMetrics: typeof aggregateDominatorMetrics;
134
137
  applyToNodes: typeof applyToNodes;
135
138
  callAsync: typeof callAsync;
136
139
  camelCaseToReadableString: typeof camelCaseToReadableString;
140
+ checkIsChildOfParent: typeof checkIsChildOfParent;
137
141
  checkSnapshots: typeof checkSnapshots;
138
142
  checkUninstalledLibrary: typeof checkUninstalledLibrary;
139
- checkIsChildOfParent: typeof checkIsChildOfParent;
140
143
  closePuppeteer: typeof closePuppeteer;
141
144
  dumpSnapshot: typeof dumpSnapshot;
142
145
  equalOrMatch: typeof equalOrMatch;
@@ -145,13 +148,14 @@ declare const _default: {
145
148
  extractHTMLElementNodeInfo: typeof extractHTMLElementNodeInfo;
146
149
  filterNodesInPlace: typeof filterNodesInPlace;
147
150
  getAllDominators: typeof getAllDominators;
151
+ getBooleanNodeValue: typeof getBooleanNodeValue;
148
152
  getClosureSourceUrl: typeof getClosureSourceUrl;
149
153
  getConditionalDominatorIds: typeof getConditionalDominatorIds;
150
- getError: typeof getError;
151
154
  getEdgeByNameAndType: typeof getEdgeByNameAndType;
155
+ getError: typeof getError;
152
156
  getLastNodeId: typeof getLastNodeId;
153
- getLeakedNode: typeof getLeakedNode;
154
157
  getLeakTracePathLength: typeof getLeakTracePathLength;
158
+ getLeakedNode: typeof getLeakedNode;
155
159
  getNodesIdSet: typeof getNodesIdSet;
156
160
  getNumberAtPercentile: typeof getNumberAtPercentile;
157
161
  getNumberNodeValue: typeof getNumberNodeValue;
@@ -159,17 +163,16 @@ declare const _default: {
159
163
  getReadablePercent: typeof getReadablePercent;
160
164
  getReadableTime: typeof getReadableTime;
161
165
  getRetainedSize: typeof getRetainedSize;
162
- getRunMetaFilePath: typeof getRunMetaFilePath;
163
166
  getScenarioName: typeof getScenarioName;
164
167
  getSingleSnapshotFileForAnalysis: typeof getSingleSnapshotFileForAnalysis;
165
168
  getSnapshotDirForAnalysis: typeof getSnapshotDirForAnalysis;
166
- getSnapshotFilesInDir: typeof getSnapshotFilesInDir;
169
+ getSnapshotFilePath: typeof getSnapshotFilePath;
170
+ getSnapshotFilePathWithTabType: typeof getSnapshotFilePathWithTabType;
167
171
  getSnapshotFilesFromTabsOrder: typeof getSnapshotFilesFromTabsOrder;
172
+ getSnapshotFilesInDir: typeof getSnapshotFilesInDir;
168
173
  getSnapshotFromFile: typeof getSnapshotFromFile;
169
174
  getSnapshotNodeIdsFromFile: typeof getSnapshotNodeIdsFromFile;
170
175
  getSnapshotSequenceFilePath: typeof getSnapshotSequenceFilePath;
171
- getSnapshotFilePath: typeof getSnapshotFilePath;
172
- getSnapshotFilePathWithTabType: typeof getSnapshotFilePathWithTabType;
173
176
  getStringNodeValue: typeof getStringNodeValue;
174
177
  getToNodeByEdge: typeof getToNodeByEdge;
175
178
  getUniqueID: typeof getUniqueID;
@@ -180,18 +183,21 @@ declare const _default: {
180
183
  hasReactEdges: typeof hasReactEdges;
181
184
  isAlternateNode: typeof isAlternateNode;
182
185
  isBlinkRootNode: typeof isBlinkRootNode;
186
+ isDOMInternalNode: typeof isDOMInternalNode;
187
+ isDOMNodeIncomplete: typeof isDOMNodeIncomplete;
188
+ isDOMTextNode: typeof isDOMTextNode;
183
189
  isDebuggableNode: typeof isDebuggableNode;
184
- isDetachedFiberNode: typeof isDetachedFiberNode;
185
190
  isDetachedDOMNode: typeof isDetachedDOMNode;
191
+ isDetachedFiberNode: typeof isDetachedFiberNode;
186
192
  isDirectPropEdge: typeof isDirectPropEdge;
187
193
  isDocumentDOMTreesRoot: typeof isDocumentDOMTreesRoot;
188
- isDOMNodeIncomplete: typeof isDOMNodeIncomplete;
189
194
  isEssentialEdge: typeof isEssentialEdge;
190
195
  isFiberNode: typeof isFiberNode;
191
196
  isFiberNodeDeletionsEdge: typeof isFiberNodeDeletionsEdge;
197
+ isGlobalHandlesNode: typeof isGlobalHandlesNode;
198
+ isHTMLDocumentNode: typeof isHTMLDocumentNode;
192
199
  isHermesInternalObject: typeof isHermesInternalObject;
193
200
  isHostRoot: typeof isHostRoot;
194
- isInterestingPath: typeof isInterestingPath;
195
201
  isMeaningfulEdge: typeof isMeaningfulEdge;
196
202
  isMeaningfulNode: typeof isMeaningfulNode;
197
203
  isNodeDominatedByDeletionsArray: typeof isNodeDominatedByDeletionsArray;
@@ -210,17 +216,18 @@ declare const _default: {
210
216
  isWeakMapEdge: typeof isWeakMapEdge;
211
217
  isWeakMapEdgeToKey: typeof isWeakMapEdgeToKey;
212
218
  isWeakMapEdgeToValue: typeof isWeakMapEdgeToValue;
219
+ isXMLDocumentNode: typeof isXMLDocumentNode;
213
220
  iterateChildFiberNodes: typeof iterateChildFiberNodes;
214
221
  iterateDescendantFiberNodes: typeof iterateDescendantFiberNodes;
215
- loadRunMetaInfo: typeof loadRunMetaInfo;
216
222
  loadLeakFilter: typeof loadLeakFilter;
217
223
  loadScenario: typeof loadScenario;
218
224
  loadTabsOrder: typeof loadTabsOrder;
219
- loadTargetInfoFromRunMeta: typeof loadTargetInfoFromRunMeta;
225
+ mapToObject: typeof mapToObject;
220
226
  markAllDetachedFiberNode: typeof markAllDetachedFiberNode;
221
227
  markAlternateFiberNode: typeof markAlternateFiberNode;
222
228
  memCache: Record<string, any>;
223
229
  normalizeBaseUrl: typeof normalizeBaseUrl;
230
+ objectToMap: typeof objectToMap;
224
231
  pathHasDetachedHTMLNode: typeof pathHasDetachedHTMLNode;
225
232
  pathHasEdgeWithIndex: typeof pathHasEdgeWithIndex;
226
233
  repeat: typeof repeat;
@@ -233,7 +240,6 @@ declare const _default: {
233
240
  shuffleArray: typeof shuffleArray;
234
241
  throwError: typeof throwError;
235
242
  upperCaseFirstCharacter: typeof upperCaseFirstCharacter;
236
- getBooleanNodeValue: typeof getBooleanNodeValue;
237
243
  };
238
244
  export default _default;
239
245
  //# sourceMappingURL=Utils.d.ts.map