@memlab/core 1.1.5 → 1.1.9

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 (120) hide show
  1. package/dist/__tests__/parser/HeapParser.test.d.ts +1 -1
  2. package/dist/__tests__/parser/HeapParser.test.js +3 -3
  3. package/dist/__tests__/parser/NodeHeap.test.d.ts +1 -1
  4. package/dist/__tests__/parser/NodeHeap.test.js +6 -6
  5. package/dist/__tests__/parser/StringNode.test.d.ts +1 -1
  6. package/dist/__tests__/parser/StringNode.test.js +2 -2
  7. package/dist/__tests__/parser/traverse/HeapNodeTraverse.test.d.ts +1 -1
  8. package/dist/__tests__/parser/traverse/HeapNodeTraverse.test.js +3 -3
  9. package/dist/__tests__/utils/utils.test.d.ts +1 -1
  10. package/dist/__tests__/utils/utils.test.js +1 -1
  11. package/dist/index.d.ts +4 -2
  12. package/dist/index.js +6 -3
  13. package/dist/lib/BaseOption.d.ts +1 -1
  14. package/dist/lib/BaseOption.js +1 -1
  15. package/dist/lib/BrowserInfo.d.ts +1 -1
  16. package/dist/lib/BrowserInfo.js +1 -1
  17. package/dist/lib/Config.d.ts +11 -2
  18. package/dist/lib/Config.js +25 -5
  19. package/dist/lib/Console.d.ts +1 -1
  20. package/dist/lib/Console.js +1 -1
  21. package/dist/lib/Constant.d.ts +1 -1
  22. package/dist/lib/Constant.js +1 -1
  23. package/dist/lib/FileManager.d.ts +1 -1
  24. package/dist/lib/FileManager.js +5 -3
  25. package/dist/lib/HeapAnalyzer.d.ts +1 -1
  26. package/dist/lib/HeapAnalyzer.js +26 -10
  27. package/dist/lib/HeapParser.d.ts +2 -2
  28. package/dist/lib/HeapParser.js +2 -2
  29. package/dist/lib/InternalValueSetter.d.ts +1 -1
  30. package/dist/lib/InternalValueSetter.js +1 -1
  31. package/dist/lib/NodeHeap.d.ts +53 -10
  32. package/dist/lib/NodeHeap.js +73 -22
  33. package/dist/lib/PackageInfoLoader.js +2 -2
  34. package/dist/lib/ProcessManager.d.ts +1 -1
  35. package/dist/lib/ProcessManager.js +1 -1
  36. package/dist/lib/Serializer.d.ts +1 -1
  37. package/dist/lib/Serializer.js +49 -26
  38. package/dist/lib/StringLoader.d.ts +2 -2
  39. package/dist/lib/StringLoader.js +2 -2
  40. package/dist/lib/Types.d.ts +111 -36
  41. package/dist/lib/Types.js +1 -1
  42. package/dist/lib/Utils.d.ts +1 -1
  43. package/dist/lib/Utils.js +55 -31
  44. package/dist/lib/heap-data/HeapEdge.d.ts +2 -2
  45. package/dist/lib/heap-data/HeapEdge.js +2 -2
  46. package/dist/lib/heap-data/HeapLocation.d.ts +2 -2
  47. package/dist/lib/heap-data/HeapLocation.js +2 -2
  48. package/dist/lib/heap-data/HeapNode.d.ts +3 -2
  49. package/dist/lib/heap-data/HeapNode.js +6 -2
  50. package/dist/lib/heap-data/HeapSnapshot.d.ts +3 -2
  51. package/dist/lib/heap-data/HeapSnapshot.js +6 -33
  52. package/dist/lib/heap-data/HeapStringNode.d.ts +2 -2
  53. package/dist/lib/heap-data/HeapStringNode.js +4 -2
  54. package/dist/lib/heap-data/HeapUtils.d.ts +2 -2
  55. package/dist/lib/heap-data/HeapUtils.js +2 -2
  56. package/dist/lib/heap-data/MemLabTagStore.d.ts +23 -0
  57. package/dist/lib/heap-data/MemLabTagStore.js +110 -0
  58. package/dist/lib/leak-filters/BaseLeakFilter.rule.d.ts +1 -1
  59. package/dist/lib/leak-filters/BaseLeakFilter.rule.js +1 -1
  60. package/dist/lib/leak-filters/LeakFilterRuleList.d.ts +1 -1
  61. package/dist/lib/leak-filters/LeakFilterRuleList.js +1 -1
  62. package/dist/lib/leak-filters/LeakObjectFilter.d.ts +1 -1
  63. package/dist/lib/leak-filters/LeakObjectFilter.js +1 -1
  64. package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.d.ts +1 -1
  65. package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.js +1 -1
  66. package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.d.ts +1 -1
  67. package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.js +1 -1
  68. package/dist/lib/leak-filters/rules/FilterHermesNode.rule.d.ts +1 -1
  69. package/dist/lib/leak-filters/rules/FilterHermesNode.rule.js +1 -1
  70. package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.d.ts +1 -1
  71. package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.js +1 -1
  72. package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.d.ts +1 -1
  73. package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.js +1 -1
  74. package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.d.ts +1 -1
  75. package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.js +1 -1
  76. package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.d.ts +1 -1
  77. package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.js +1 -1
  78. package/dist/logger/LeakClusterLogger.d.ts +1 -1
  79. package/dist/logger/LeakClusterLogger.js +1 -1
  80. package/dist/logger/LeakTraceDetailsLogger.d.ts +1 -1
  81. package/dist/logger/LeakTraceDetailsLogger.js +1 -1
  82. package/dist/modes/BaseMode.d.ts +1 -1
  83. package/dist/modes/BaseMode.js +1 -1
  84. package/dist/modes/InteractionTestMode.d.ts +1 -1
  85. package/dist/modes/InteractionTestMode.js +1 -1
  86. package/dist/modes/MeasureMode.d.ts +1 -1
  87. package/dist/modes/MeasureMode.js +1 -1
  88. package/dist/modes/RunningModes.d.ts +1 -1
  89. package/dist/modes/RunningModes.js +1 -1
  90. package/dist/paths/TraceFinder.d.ts +1 -1
  91. package/dist/paths/TraceFinder.js +41 -42
  92. package/dist/trace-cluster/ClusterUtils.d.ts +1 -1
  93. package/dist/trace-cluster/ClusterUtils.js +1 -1
  94. package/dist/trace-cluster/ClusterUtilsHelper.d.ts +1 -1
  95. package/dist/trace-cluster/ClusterUtilsHelper.js +1 -1
  96. package/dist/trace-cluster/ClusteringHeuristics.d.ts +1 -1
  97. package/dist/trace-cluster/ClusteringHeuristics.js +1 -1
  98. package/dist/trace-cluster/EvalutationMetric.d.ts +1 -1
  99. package/dist/trace-cluster/EvalutationMetric.js +1 -1
  100. package/dist/trace-cluster/SequentialClustering.d.ts +17 -0
  101. package/dist/trace-cluster/SequentialClustering.js +47 -0
  102. package/dist/trace-cluster/TraceBucket.d.ts +2 -1
  103. package/dist/trace-cluster/TraceBucket.js +10 -2
  104. package/dist/trace-cluster/TraceElement.d.ts +3 -1
  105. package/dist/trace-cluster/TraceElement.js +7 -1
  106. package/dist/trace-cluster/strategies/MLTraceSimilarityStrategy.d.ts +15 -0
  107. package/dist/trace-cluster/strategies/MLTraceSimilarityStrategy.js +61 -0
  108. package/dist/trace-cluster/strategies/TraceAsClusterStrategy.d.ts +1 -1
  109. package/dist/trace-cluster/strategies/TraceAsClusterStrategy.js +1 -1
  110. package/dist/trace-cluster/strategies/TraceSimilarityStrategy.d.ts +1 -1
  111. package/dist/trace-cluster/strategies/TraceSimilarityStrategy.js +1 -1
  112. package/dist/trace-cluster/strategies/machine-learning/DistanceMatrix.d.ts +11 -0
  113. package/dist/trace-cluster/strategies/machine-learning/DistanceMatrix.js +54 -0
  114. package/dist/trace-cluster/strategies/machine-learning/HAC.d.ts +17 -0
  115. package/dist/trace-cluster/strategies/machine-learning/HAC.js +122 -0
  116. package/dist/trace-cluster/strategies/machine-learning/Ngram.d.ts +11 -0
  117. package/dist/trace-cluster/strategies/machine-learning/Ngram.js +22 -0
  118. package/dist/trace-cluster/strategies/machine-learning/TfidfVectorizer.d.ts +38 -0
  119. package/dist/trace-cluster/strategies/machine-learning/TfidfVectorizer.js +144 -0
  120. package/package.json +1 -1
@@ -4,8 +4,8 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @emails oncall+ws_labs
8
7
  * @format
8
+ * @oncall ws_labs
9
9
  */
10
10
  import { ParsedArgs } from 'minimist';
11
11
  import type { LaunchOptions, Page } from 'puppeteer';
@@ -32,7 +32,6 @@ export declare type AnyOptions = Record<string, unknown>;
32
32
  export declare type UnusedOptions = Record<string, never>;
33
33
  /** @internal */
34
34
  export declare type Command = [string, string[], AnyOptions];
35
- export declare type Predicator<T> = (node: T) => boolean;
36
35
  /** @internal */
37
36
  export declare type HeapNodeIdSet = Set<number>;
38
37
  /** @internal */
@@ -86,6 +85,22 @@ export declare type CLIArgs = {
86
85
  'local-puppeteer': boolean;
87
86
  'snapshot-dir': string;
88
87
  };
88
+ /**
89
+ * the predicate callback is used to decide if a
90
+ * entity of type `T`.
91
+ * For more concrete examples on where it is used,
92
+ * check out {@link findAnyReference}, {@link findAnyReferrer},
93
+ * and {@link findReferrers}.
94
+ *
95
+ * @typeParam T - the type of the entity to be checked
96
+ * @param entity - the entity to be checked
97
+ * @returns whether the entity passes the predicate check
98
+ */
99
+ export declare type Predicator<T> = (entity: T) => boolean;
100
+ /**
101
+ * Data structure for holding cookies.
102
+ * For concrete example, check out {@link cookies}.
103
+ */
89
104
  export declare type Cookies = Array<{
90
105
  name: string;
91
106
  value: string;
@@ -288,9 +303,10 @@ export interface ILeakFilter {
288
303
  /**
289
304
  * Lifecycle function callback that is invoked initially once before calling any
290
305
  * leak filter function.
306
+ * For concrete example, check out {@link beforeLeakFilter}.
291
307
  *
292
- * @param snaphost - heap snapshot see {@link IHeapSnapshot}
293
- * @param leakedNodeIds - the set of leaked object (node) ids.
308
+ * @param snapshot heap snapshot see {@link IHeapSnapshot}
309
+ * @param leakedNodeIds the set of leaked object (node) ids.
294
310
  */
295
311
  export declare type InitLeakFilterCallback = (snapshot: IHeapSnapshot, leakedNodeIds: HeapNodeIdSet) => void;
296
312
  /**
@@ -299,6 +315,8 @@ export declare type InitLeakFilterCallback = (snapshot: IHeapSnapshot, leakedNod
299
315
  * allocated but not released from the target interaction
300
316
  * in the heap snapshot.
301
317
  *
318
+ * For concrete examples, check out {@link leakFilter}.
319
+ *
302
320
  * @param node - the node that is kept alive in the memory in the heap snapshot
303
321
  * @param snapshot - the snapshot of target interaction
304
322
  * @param leakedNodeIds - the set of leaked node ids
@@ -317,6 +335,11 @@ export declare type LeakFilterCallback = (node: IHeapNode, snapshot: IHeapSnapsh
317
335
  /**
318
336
  * The callback defines browser interactions which are
319
337
  * used by memlab to interact with the web app under test.
338
+ * For concrete examples, check out {@link action} or {@link back}.
339
+ *
340
+ * @param page the puppeteer [`Page`](https://pptr.dev/api/puppeteer.page)
341
+ * object, which provides APIs to interact with the web browser
342
+ * @returns no return value
320
343
  */
321
344
  export declare type InteractionsCallback = (page: Page, args?: OperationArgs) => Promise<void>;
322
345
  /**
@@ -684,6 +707,7 @@ export interface IDataBuilder {
684
707
  }
685
708
  /**
686
709
  * Callback function to provide if the page is loaded.
710
+ * For concrete example, check out {@link isPageLoaded}.
687
711
  * @param page - puppeteer's [Page](https://pptr.dev/api/puppeteer.page/) object.
688
712
  * @returns a boolean value, if it returns `true`, memlab will consider
689
713
  * the navigation completes, if it returns `false`, memlab will keep calling
@@ -738,16 +762,42 @@ export declare type E2EStepInfo = IE2EStepBasic & {
738
762
  delay?: number;
739
763
  metrics: Record<string, number>;
740
764
  };
741
- /** @internal */
765
+ /**
766
+ * This data structure contains the input configuration for the browser and
767
+ * output data from the browser. You can retrieve the instance of this type
768
+ * through {@link RunMetaInfo}.
769
+ */
742
770
  export interface IBrowserInfo {
771
+ /**
772
+ * browser version
773
+ */
743
774
  _browserVersion: string;
775
+ /**
776
+ * configuration for puppeteer
777
+ */
744
778
  _puppeteerConfig: LaunchOptions;
779
+ /**
780
+ * all web console output
781
+ */
745
782
  _consoleMessages: string[];
746
783
  }
784
+ /**
785
+ * This data structure holds the information about memlab run.
786
+ * You can retrieve the instance of this type through {@link getRunMetaInfo}.
787
+ */
747
788
  export declare type RunMetaInfo = {
789
+ /** @internal */
748
790
  app: string;
791
+ /** @internal */
749
792
  interaction: string;
793
+ /**
794
+ * type of the memlab run
795
+ */
750
796
  type: string;
797
+ /**
798
+ * input configuration for the browser and
799
+ * output data from the browser
800
+ */
751
801
  browserInfo: IBrowserInfo;
752
802
  };
753
803
  /**
@@ -757,6 +807,13 @@ export declare type RunMetaInfo = {
757
807
  * {@link IHeapNode} and {@link IHeapEdge}.
758
808
  */
759
809
  export interface IHeapSnapshot {
810
+ /**
811
+ * flag indicating if the heap snapshot has included
812
+ * the post-processing meta data (e.g., shortest path to GC root,
813
+ * dominator info and retainer size etc.)
814
+ * @internal
815
+ */
816
+ isProcessed: boolean;
760
817
  /** @internal */
761
818
  snapshot: RawHeapSnapshot;
762
819
  /**
@@ -769,11 +826,11 @@ export interface IHeapSnapshot {
769
826
  * ```typescript
770
827
  * import type {IHeapSnapshot, IHeapNode} from '@memlab/core';
771
828
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
772
- * import {getHeapFromFile} from '@memlab/heap-analysis';
829
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
773
830
  *
774
831
  * (async function () {
775
832
  * const heapFile = dumpNodeHeapSnapshot();
776
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
833
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
777
834
  *
778
835
  * // get the total number of heap objects
779
836
  * heap.nodes.length;
@@ -795,11 +852,11 @@ export interface IHeapSnapshot {
795
852
  * ```typescript
796
853
  * import type {IHeapSnapshot, IHeapEdge} from '@memlab/core';
797
854
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
798
- * import {getHeapFromFile} from '@memlab/heap-analysis';
855
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
799
856
  *
800
857
  * (async function () {
801
858
  * const heapFile = dumpNodeHeapSnapshot();
802
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
859
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
803
860
  *
804
861
  * // get the total number of heap references
805
862
  * heap.edges.length;
@@ -821,11 +878,11 @@ export interface IHeapSnapshot {
821
878
  * ```typescript
822
879
  * import type {IHeapSnapshot} from '@memlab/core';
823
880
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
824
- * import {getHeapFromFile} from '@memlab/heap-analysis';
881
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
825
882
  *
826
883
  * (async function () {
827
884
  * const heapFile = dumpNodeHeapSnapshot();
828
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
885
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
829
886
  *
830
887
  * const node = heap.getNodeById(351);
831
888
  * node?.id; // should be 351
@@ -843,7 +900,7 @@ export interface IHeapSnapshot {
843
900
  * ```typescript
844
901
  * // save as example.test.ts
845
902
  * import type {IHeapSnapshot, Nullable} from '@memlab/core';
846
- * import {config, getNodeInnocentHeap} from '@memlab/core';
903
+ * import {config, takeNodeMinimalHeap} from '@memlab/core';
847
904
  *
848
905
  * class TestObject {
849
906
  * public arr1 = [1, 2, 3];
@@ -855,7 +912,7 @@ export interface IHeapSnapshot {
855
912
  *
856
913
  * let obj: Nullable<TestObject> = new TestObject();
857
914
  * // get a heap snapshot of the current program state
858
- * let heap: IHeapSnapshot = await getNodeInnocentHeap();
915
+ * let heap: IHeapSnapshot = await takeNodeMinimalHeap();
859
916
  *
860
917
  * // call some function that may add references to obj
861
918
  * rabbitHole(obj)
@@ -863,7 +920,7 @@ export interface IHeapSnapshot {
863
920
  * expect(heap.hasObjectWithClassName('TestObject')).toBe(true);
864
921
  * obj = null;
865
922
  *
866
- * heap = await getNodeInnocentHeap();
923
+ * heap = await takeNodeMinimalHeap();
867
924
  * // if rabbitHole does not have any side effect that
868
925
  * // adds new references to obj, then obj can be GCed
869
926
  * expect(heap.hasObjectWithClassName('TestObject')).toBe(false);
@@ -882,7 +939,7 @@ export interface IHeapSnapshot {
882
939
  * * **Examples**:
883
940
  * ```typescript
884
941
  * import type {IHeapSnapshot} from '@memlab/core';
885
- * import {getNodeInnocentHeap} from '@memlab/core';
942
+ * import {takeNodeMinimalHeap} from '@memlab/core';
886
943
  *
887
944
  * class TestObject {
888
945
  * public arr1 = [1, 2, 3];
@@ -892,7 +949,7 @@ export interface IHeapSnapshot {
892
949
  * (async function () {
893
950
  * const obj = new TestObject();
894
951
  * // get a heap snapshot of the current program state
895
- * const heap: IHeapSnapshot = await getNodeInnocentHeap();
952
+ * const heap: IHeapSnapshot = await takeNodeMinimalHeap();
896
953
  *
897
954
  * const node = heap.getAnyObjectWithClassName('TestObject');
898
955
  * console.log(node?.name); // should be 'TestObject'
@@ -911,14 +968,14 @@ export interface IHeapSnapshot {
911
968
  * ```typescript
912
969
  * import type {IHeapSnapshot} from '@memlab/core';
913
970
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
914
- * import {getHeapFromFile} from '@memlab/heap-analysis';
971
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
915
972
  *
916
973
  * (async function () {
917
974
  * // eslint-disable-next-line @typescript-eslint/no-unused-vars
918
975
  * const object = {'memlab-test-heap-property': 'memlab-test-heap-value'};
919
976
  *
920
977
  * const heapFile = dumpNodeHeapSnapshot();
921
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
978
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
922
979
  *
923
980
  * // should be true
924
981
  * console.log(heap.hasObjectWithPropertyName('memlab-test-heap-property'));
@@ -938,7 +995,7 @@ export interface IHeapSnapshot {
938
995
  *
939
996
  * ```typescript
940
997
  * import type {IHeapSnapshot, AnyValue} from '@memlab/core';
941
- * import {config, getNodeInnocentHeap, tagObject} from '@memlab/core';
998
+ * import {config, takeNodeMinimalHeap, tagObject} from '@memlab/core';
942
999
  *
943
1000
  * test('memory test', async () => {
944
1001
  * config.muteConsole = true;
@@ -952,7 +1009,7 @@ export interface IHeapSnapshot {
952
1009
  *
953
1010
  * o2 = null;
954
1011
  *
955
- * const heap: IHeapSnapshot = await getNodeInnocentHeap();
1012
+ * const heap: IHeapSnapshot = await takeNodeMinimalHeap();
956
1013
  *
957
1014
  * // expect object with marker "memlab-mark-1" exists
958
1015
  * expect(heap.hasObjectWithTag('memlab-mark-1')).toBe(true);
@@ -976,16 +1033,16 @@ export interface IHeapSnapshot {
976
1033
  * @readonly it is not recommended to modify any `IHeapLocation` instance
977
1034
  *
978
1035
  * * **Examples**: V8 or hermes heap snapshot can be parsed by the
979
- * {@link getHeapFromFile} API.
1036
+ * {@link getFullHeapFromFile} API.
980
1037
  *
981
1038
  * ```typescript
982
1039
  * import type {IHeapSnapshot, IHeapNode, IHeapLocation} from '@memlab/core';
983
1040
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
984
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1041
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
985
1042
  *
986
1043
  * (async function () {
987
1044
  * const heapFile = dumpNodeHeapSnapshot();
988
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1045
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
989
1046
  *
990
1047
  * // iterate over each node (heap object)
991
1048
  * heap.nodes.forEach((node: IHeapNode, i: number) => {
@@ -1038,16 +1095,16 @@ export interface IHeapEdgeBasic {
1038
1095
  * @readonly it is not recommended to modify any `IHeapEdge` instance
1039
1096
  *
1040
1097
  * * **Examples**: V8 or hermes heap snapshot can be parsed by the
1041
- * {@link getHeapFromFile} API.
1098
+ * {@link getFullHeapFromFile} API.
1042
1099
  *
1043
1100
  * ```typescript
1044
1101
  * import type {IHeapSnapshot, IHeapEdge} from '@memlab/core';
1045
1102
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
1046
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1103
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
1047
1104
  *
1048
1105
  * (async function () {
1049
1106
  * const heapFile = dumpNodeHeapSnapshot();
1050
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1107
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
1051
1108
  *
1052
1109
  * // iterate over each edge (JS reference in heap)
1053
1110
  * heap.edges.forEach((edge: IHeapEdge, i: number) => {
@@ -1101,11 +1158,11 @@ export interface IHeapEdge extends IHeapEdgeBasic {
1101
1158
  * ```typescript
1102
1159
  * import type {IHeapSnapshot, IHeapEdges} from '@memlab/core';
1103
1160
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
1104
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1161
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
1105
1162
  *
1106
1163
  * (async function () {
1107
1164
  * const heapFile = dumpNodeHeapSnapshot();
1108
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1165
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
1109
1166
  *
1110
1167
  * const edges: IHeapEdges = heap.edges;
1111
1168
  * edges.length;
@@ -1162,6 +1219,13 @@ export interface IHeapNodeBasic {
1162
1219
  */
1163
1220
  id: number;
1164
1221
  }
1222
+ /**
1223
+ * Executes a provided callback once for JavaScript references.
1224
+ * For concrete examples, check out {@link forEachReference}
1225
+ * or {@link forEachReferrer}.
1226
+ * @param callback the callback for each JavaScript reference from a collection
1227
+ * @returns this API returns void
1228
+ */
1165
1229
  export declare type EdgeIterationCallback = (edge: IHeapEdge) => Optional<{
1166
1230
  stop: boolean;
1167
1231
  }>;
@@ -1173,16 +1237,16 @@ export declare type EdgeIterationCallback = (edge: IHeapEdge) => Optional<{
1173
1237
  * @readonly it is not recommended to modify any `IHeapNode` instance
1174
1238
  *
1175
1239
  * * **Examples**: V8 or hermes heap snapshot can be parsed by the
1176
- * {@link getHeapFromFile} API.
1240
+ * {@link getFullHeapFromFile} API.
1177
1241
  *
1178
1242
  * ```typescript
1179
1243
  * import type {IHeapSnapshot, IHeapNode} from '@memlab/core';
1180
1244
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
1181
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1245
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
1182
1246
  *
1183
1247
  * (async function () {
1184
1248
  * const heapFile = dumpNodeHeapSnapshot();
1185
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1249
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
1186
1250
  *
1187
1251
  * // iterate over each node (heap object)
1188
1252
  * heap.nodes.forEach((node: IHeapNode, i: number) => {
@@ -1237,6 +1301,11 @@ export interface IHeapNode extends IHeapNodeBasic {
1237
1301
  * object (including engine-internal, native, and JS references).
1238
1302
  */
1239
1303
  referrers: IHeapEdge[];
1304
+ /**
1305
+ * returns true if the heap node has been set an incoming edge
1306
+ * which leads to the parent node on the shortest path to GC root.
1307
+ */
1308
+ hasPathEdge: boolean;
1240
1309
  /**
1241
1310
  * The incoming edge which leads to the parent node
1242
1311
  * on the shortest path to GC root.
@@ -1481,16 +1550,16 @@ export interface IHeapNode extends IHeapNodeBasic {
1481
1550
  * @readonly it is not recommended to modify any `IHeapStringNode` instance
1482
1551
  *
1483
1552
  * * **Examples**: V8 or hermes heap snapshot can be parsed by the
1484
- * {@link getHeapFromFile} API.
1553
+ * {@link getFullHeapFromFile} API.
1485
1554
  *
1486
1555
  * ```typescript
1487
1556
  * import type {IHeapSnapshot, IHeapNode, IHeapStringNode} from '@memlab/core';
1488
1557
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
1489
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1558
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
1490
1559
  *
1491
1560
  * (async function () {
1492
1561
  * const heapFile = dumpNodeHeapSnapshot();
1493
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1562
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
1494
1563
  *
1495
1564
  * // iterate over each node (heap object)
1496
1565
  * heap.nodes.forEach((node: IHeapNode, i: number) => {
@@ -1522,11 +1591,11 @@ export interface IHeapStringNode extends IHeapNode {
1522
1591
  * ```typescript
1523
1592
  * import type {IHeapSnapshot, IHeapNodes} from '@memlab/core';
1524
1593
  * import {dumpNodeHeapSnapshot} from '@memlab/core';
1525
- * import {getHeapFromFile} from '@memlab/heap-analysis';
1594
+ * import {getFullHeapFromFile} from '@memlab/heap-analysis';
1526
1595
  *
1527
1596
  * (async function () {
1528
1597
  * const heapFile = dumpNodeHeapSnapshot();
1529
- * const heap: IHeapSnapshot = await getHeapFromFile(heapFile);
1598
+ * const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
1530
1599
  *
1531
1600
  * const nodes: IHeapNodes = heap.nodes;
1532
1601
  * nodes.length;
@@ -1661,5 +1730,11 @@ export interface IClusterStrategy {
1661
1730
  diffTraces: (newLeakTraces: LeakTrace[], existingLeakTraces: LeakTrace[]) => TraceDiff;
1662
1731
  }
1663
1732
  /** @internal */
1733
+ export interface IHeapConfig {
1734
+ isCliInteractiveMode: boolean;
1735
+ currentHeapFile: Optional<string>;
1736
+ currentHeap: Optional<IHeapSnapshot>;
1737
+ }
1738
+ /** @internal */
1664
1739
  export declare type ErrorWithMessage = Pick<Error, 'message'>;
1665
1740
  //# sourceMappingURL=Types.d.ts.map
package/dist/lib/Types.js CHANGED
@@ -5,8 +5,8 @@
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  *
8
- * @emails oncall+ws_labs
9
8
  * @format
9
+ * @oncall ws_labs
10
10
  */
11
11
  /* eslint-disable @typescript-eslint/no-explicit-any */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -4,8 +4,8 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @emails oncall+ws_labs
8
7
  * @format
8
+ * @oncall ws_labs
9
9
  */
10
10
  import type { HaltOrThrowOptions } from './Types';
11
11
  import type { Browser, Page } from 'puppeteer';
package/dist/lib/Utils.js CHANGED
@@ -5,8 +5,8 @@
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  *
8
- * @emails oncall+ws_labs
9
8
  * @format
9
+ * @oncall ws_labs
10
10
  */
11
11
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
12
  if (k2 === undefined) k2 = k;
@@ -136,10 +136,10 @@ function isDetachedFiberNode(node) {
136
136
  // any detached DOM nodes (e.g., HTMLXXElement, IntersectionObserver etc.)
137
137
  // that are not internal nodes.
138
138
  function isDetachedDOMNode(node, args = {}) {
139
- if (!node || typeof node.name !== 'string') {
139
+ let name = null;
140
+ if (!node || typeof (name = node.name) !== 'string') {
140
141
  return false;
141
142
  }
142
- const name = node.name;
143
143
  if (isFiberNode(node)) {
144
144
  return false;
145
145
  }
@@ -213,13 +213,16 @@ function isPendingActivityNode(node) {
213
213
  return node.type === 'synthetic' && node.name === 'Pending activities';
214
214
  }
215
215
  function isRootNode(node, opt = {}) {
216
- if (!node || !node.name) {
216
+ if (!node) {
217
217
  return false;
218
218
  }
219
219
  // consider Hermes snapshot GC roots
220
220
  if (Config_1.default.jsEngine === 'hermes') {
221
221
  return node.name === '(GC roots)' || node.name === '(GC Roots)';
222
222
  }
223
+ if (node.id === 0 || node.id === 1) {
224
+ return true;
225
+ }
223
226
  // the window object
224
227
  if (node.type === 'native' && node.name.indexOf('Window') === 0) {
225
228
  return true;
@@ -390,7 +393,6 @@ function setFiberNodeAttribute(node, flag) {
390
393
  if (!node || !isFiberNode(node)) {
391
394
  return;
392
395
  }
393
- // eslint-disable-next-line no-bitwise
394
396
  node.attributes |= flag;
395
397
  }
396
398
  function hasFiberNodeAttribute(node, flag) {
@@ -447,7 +449,6 @@ function filterNodesInPlace(idSet, snapshot, cb) {
447
449
  function applyToNodes(idSet, snapshot, cb, options = {}) {
448
450
  let ids = Array.from(idSet.keys());
449
451
  if (options.shuffle) {
450
- // eslint-disable-next-line fb-www/unsafe-math-random
451
452
  ids.sort(() => Math.random() - 0.5);
452
453
  }
453
454
  else if (options.reverse) {
@@ -508,7 +509,6 @@ function loadScenario(filename) {
508
509
  }
509
510
  let scenario;
510
511
  try {
511
- // eslint-disable-next-line @typescript-eslint/no-var-requires
512
512
  scenario = require(filepath);
513
513
  scenario = checkScenarioInstance(scenario);
514
514
  if (scenario.name == null) {
@@ -534,6 +534,12 @@ function handleSnapshotError(e) {
534
534
  }
535
535
  function getSnapshotFromFile(filename, options) {
536
536
  return __awaiter(this, void 0, void 0, function* () {
537
+ const heapConfig = Config_1.default.heapConfig;
538
+ if (heapConfig &&
539
+ heapConfig.currentHeapFile === filename &&
540
+ heapConfig.currentHeap) {
541
+ return heapConfig.currentHeap;
542
+ }
537
543
  Console_1.default.overwrite('parsing ' + filename + ' ...');
538
544
  let ret = null;
539
545
  try {
@@ -812,7 +818,6 @@ function loadRunMetaInfo(metaFile = undefined) {
812
818
  try {
813
819
  const content = fs_1.default.readFileSync(file, 'UTF-8');
814
820
  return JSON.parse(content);
815
- // eslint-disable-next-line fb-www/no-unused-catch-bindings
816
821
  }
817
822
  catch (_) {
818
823
  throw haltOrThrow('Run info missing. Please make sure `memlab run` is complete.');
@@ -1271,9 +1276,23 @@ function getSnapshotDirForAnalysis() {
1271
1276
  return dir;
1272
1277
  }
1273
1278
  function getSingleSnapshotFileForAnalysis() {
1274
- const path = Config_1.default.useExternalSnapshot && Config_1.default.externalSnapshotFilePaths[0]
1275
- ? Config_1.default.externalSnapshotFilePaths[0]
1276
- : getSnapshotFilePathWithTabType(/(final)|(target)|(baseline)/);
1279
+ let path = null;
1280
+ // if an external snapshot file is specified
1281
+ if (Config_1.default.useExternalSnapshot &&
1282
+ Config_1.default.externalSnapshotFilePaths.length > 0) {
1283
+ path =
1284
+ Config_1.default.externalSnapshotFilePaths[Config_1.default.externalSnapshotFilePaths.length - 1];
1285
+ // if running in interactive heap analysis mode
1286
+ }
1287
+ else if (Config_1.default.heapConfig &&
1288
+ Config_1.default.heapConfig.isCliInteractiveMode &&
1289
+ Config_1.default.heapConfig.currentHeapFile) {
1290
+ path = Config_1.default.heapConfig.currentHeapFile;
1291
+ // search for snapshot labeled as baseline, target, or final
1292
+ }
1293
+ else {
1294
+ path = getSnapshotFilePathWithTabType(/(final)|(target)|(baseline)/);
1295
+ }
1277
1296
  return resolveSnapshotFilePath(path);
1278
1297
  }
1279
1298
  function getSnapshotFilePath(tab) {
@@ -1286,7 +1305,7 @@ function getSnapshotFilePath(tab) {
1286
1305
  }
1287
1306
  return Config_1.default.externalSnapshotFilePaths[tab.idx - 1];
1288
1307
  }
1289
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
1308
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1290
1309
  function equalOrMatch(v1, v2) {
1291
1310
  const t1 = typeof v1;
1292
1311
  const t2 = typeof v2;
@@ -1319,7 +1338,8 @@ function isMeaningfulNode(node) {
1319
1338
  if (!node) {
1320
1339
  return false;
1321
1340
  }
1322
- if (Config_1.default.nodeNameBlockList.has(node.name)) {
1341
+ const nodeName = node.name;
1342
+ if (Config_1.default.nodeNameBlockList.has(nodeName)) {
1323
1343
  return false;
1324
1344
  }
1325
1345
  if (isFiberNode(node)) {
@@ -1330,13 +1350,13 @@ function isMeaningfulNode(node) {
1330
1350
  }
1331
1351
  // More details in https://github.com/ChromeDevTools/devtools-frontend
1332
1352
  // under front_end/heap_snapshot_worker/HeapSnapshot.ts
1333
- if (node.name === 'system / NativeContext') {
1353
+ if (nodeName === 'system / NativeContext') {
1334
1354
  return false;
1335
1355
  }
1336
- if (node.name === 'system / SourcePositionTableWithFrameCache') {
1356
+ if (nodeName === 'system / SourcePositionTableWithFrameCache') {
1337
1357
  return false;
1338
1358
  }
1339
- if (node.name === '(map descriptors)') {
1359
+ if (nodeName === '(map descriptors)') {
1340
1360
  return false;
1341
1361
  }
1342
1362
  if (node.type === 'code') {
@@ -1351,44 +1371,49 @@ function isMeaningfulEdge(edge, options = {}) {
1351
1371
  if (source.id === node.id) {
1352
1372
  return false;
1353
1373
  }
1354
- if (typeof edge.name_or_index === 'string' &&
1355
- Config_1.default.edgeNameBlockList.has(edge.name_or_index)) {
1374
+ const edgeNameOrIndex = edge.name_or_index;
1375
+ if (typeof edgeNameOrIndex === 'string' &&
1376
+ Config_1.default.edgeNameBlockList.has(edgeNameOrIndex)) {
1356
1377
  return false;
1357
1378
  }
1379
+ const edgeType = edge.type;
1358
1380
  // shortcut edge may be meaningful edges
1359
1381
  // --forceUpdate (variable)---> [native_bind]
1360
1382
  // --bound_argument_0 (shortcut)---> [FiberNode]
1361
- if (edge.type === 'weak' /* || edge.type === 'shortcut' */) {
1383
+ if (edgeType === 'weak' /* || edge.type === 'shortcut' */) {
1362
1384
  return false;
1363
1385
  }
1364
1386
  if (options.excludeWeakMapEdge && isWeakMapEdgeToKey(edge)) {
1365
1387
  return false;
1366
1388
  }
1367
- if (options.visited && options.visited[node.nodeIndex]) {
1389
+ const nodeIndex = node.nodeIndex;
1390
+ if (options.visited && options.visited[nodeIndex]) {
1368
1391
  return false;
1369
1392
  }
1370
- if (options.queued && options.queued[node.nodeIndex]) {
1393
+ if (options.queued && options.queued[nodeIndex]) {
1371
1394
  return false;
1372
1395
  }
1373
- if (!options.includeString && node.type === 'string') {
1396
+ const nodeType = node.type;
1397
+ if (!options.includeString && nodeType === 'string') {
1374
1398
  return false;
1375
1399
  }
1376
- if (edge.type === 'internal' && edge.name_or_index === 'code') {
1400
+ if (edgeType === 'internal' && edgeNameOrIndex === 'code') {
1377
1401
  return false;
1378
1402
  }
1379
1403
  // More details about the following three special cases are available
1380
1404
  // in https://github.com/ChromeDevTools/devtools-frontend
1381
1405
  // under front_end/heap_snapshot_worker/HeapSnapshot.ts
1382
- if (edge.type === 'hidden' && edge.name_or_index === 'sloppy_function_map') {
1406
+ if (edgeType === 'hidden' && edgeNameOrIndex === 'sloppy_function_map') {
1383
1407
  return false;
1384
1408
  }
1385
- if (edge.type === 'hidden' && node.name === 'system / NativeContext') {
1409
+ const nodeName = node.name;
1410
+ if (edgeType === 'hidden' && nodeName === 'system / NativeContext') {
1386
1411
  return false;
1387
1412
  }
1388
1413
  // In v8, (map descriptors) are fixed-length descriptors arrays used
1389
1414
  // to hold JS descriptors.
1390
- if (node.type === 'array' && node.name === '(map descriptors)') {
1391
- const index = edge.name_or_index;
1415
+ if (edgeType === 'array' && nodeName === '(map descriptors)') {
1416
+ const index = edgeNameOrIndex;
1392
1417
  // only elements at particular indexes of (map descriptors) are holding
1393
1418
  // representative references to objects.
1394
1419
  if (index >= 2 || (typeof index === 'number' && index % 3 === 1)) {
@@ -1401,12 +1426,12 @@ function isMeaningfulEdge(edge, options = {}) {
1401
1426
  if (Config_1.default.jsEngine === 'hermes' && isDirectPropEdge(edge)) {
1402
1427
  return false;
1403
1428
  }
1404
- if (Config_1.default.ignoreInternalNode && node.name.includes('InternalNode')) {
1429
+ if (Config_1.default.ignoreInternalNode && nodeName.includes('InternalNode')) {
1405
1430
  return false;
1406
1431
  }
1407
1432
  if (Config_1.default.ignoreDevToolsConsoleLeak) {
1408
- const name = edge.name_or_index;
1409
- if (typeof name === 'string' && name.includes('DevTools console')) {
1433
+ if (typeof edgeNameOrIndex === 'string' &&
1434
+ edgeNameOrIndex.includes('DevTools console')) {
1410
1435
  return false;
1411
1436
  }
1412
1437
  }
@@ -1421,7 +1446,6 @@ function isURLEqual(url1, url2) {
1421
1446
  try {
1422
1447
  u1 = new URL(url1);
1423
1448
  u2 = new URL(url2);
1424
- // eslint-disable-next-line fb-www/no-unused-catch-bindings
1425
1449
  }
1426
1450
  catch (_e) {
1427
1451
  return false;
@@ -4,9 +4,9 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @emails oncall+ws_labs
8
- * @lightSyntaxTransform
9
7
  * @format
8
+ * @lightSyntaxTransform
9
+ * @oncall ws_labs
10
10
  */
11
11
  import type { IHeapEdge } from '../Types';
12
12
  import type HeapSnapshot from './HeapSnapshot';
@@ -4,9 +4,9 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @emails oncall+ws_labs
8
- * @lightSyntaxTransform
9
7
  * @format
8
+ * @lightSyntaxTransform
9
+ * @oncall ws_labs
10
10
  */
11
11
  'use strict';
12
12
  var __importDefault = (this && this.__importDefault) || function (mod) {