@memlab/core 1.0.8 → 1.0.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 (35) hide show
  1. package/dist/index.d.ts +17 -0
  2. package/dist/index.js +17 -0
  3. package/dist/lib/Config.d.ts +5 -2
  4. package/dist/lib/Config.js +9 -2
  5. package/dist/lib/FileManager.d.ts +2 -0
  6. package/dist/lib/FileManager.js +1 -0
  7. package/dist/lib/HeapAnalyzer.d.ts +2 -2
  8. package/dist/lib/HeapAnalyzer.js +27 -60
  9. package/dist/lib/InternalValueSetter.d.ts +2 -0
  10. package/dist/lib/InternalValueSetter.js +2 -0
  11. package/dist/lib/Types.d.ts +63 -6
  12. package/dist/lib/Utils.js +24 -1
  13. package/dist/lib/leak-filters/BaseLeakFilter.rule.d.ts +24 -0
  14. package/dist/lib/leak-filters/BaseLeakFilter.rule.js +22 -0
  15. package/dist/lib/leak-filters/LeakFilterRuleList.d.ts +13 -0
  16. package/dist/lib/leak-filters/LeakFilterRuleList.js +33 -0
  17. package/dist/lib/leak-filters/LeakObjectFilter.d.ts +19 -0
  18. package/dist/lib/leak-filters/LeakObjectFilter.js +36 -0
  19. package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.d.ts +19 -0
  20. package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.js +27 -0
  21. package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.d.ts +20 -0
  22. package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.js +40 -0
  23. package/dist/lib/leak-filters/rules/FilterHermesNode.rule.d.ts +16 -0
  24. package/dist/lib/leak-filters/rules/FilterHermesNode.rule.js +27 -0
  25. package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.d.ts +19 -0
  26. package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.js +27 -0
  27. package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.d.ts +19 -0
  28. package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.js +28 -0
  29. package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.d.ts +20 -0
  30. package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.js +33 -0
  31. package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.d.ts +20 -0
  32. package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.js +37 -0
  33. package/dist/trace-cluster/TraceBucket.d.ts +1 -0
  34. package/dist/trace-cluster/TraceBucket.js +12 -1
  35. package/package.json +2 -1
@@ -0,0 +1,27 @@
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
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FilterOverSizedNodeAsLeakRule = void 0;
13
+ const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
14
+ /**
15
+ * trivial nodes are not reported as memory leaks
16
+ */
17
+ class FilterOverSizedNodeAsLeakRule {
18
+ filter(config, node) {
19
+ if (config.oversizeObjectAsLeak) {
20
+ return node.retainedSize > config.oversizeThreshold
21
+ ? BaseLeakFilter_rule_1.LeakDecision.LEAK
22
+ : BaseLeakFilter_rule_1.LeakDecision.NOT_LEAK;
23
+ }
24
+ return BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
25
+ }
26
+ }
27
+ exports.FilterOverSizedNodeAsLeakRule = FilterOverSizedNodeAsLeakRule;
@@ -0,0 +1,19 @@
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
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { MemLabConfig } from '../../Config';
11
+ import type { IHeapNode } from '../../Types';
12
+ import { ILeakObjectFilterRule, LeakDecision } from '../BaseLeakFilter.rule';
13
+ /**
14
+ * stack trace frames as memory leaks
15
+ */
16
+ export declare class FilterStackTraceFrameRule implements ILeakObjectFilterRule {
17
+ filter(_config: MemLabConfig, node: IHeapNode): LeakDecision;
18
+ }
19
+ //# sourceMappingURL=FilterStackTraceFrame.rule.d.ts.map
@@ -0,0 +1,28 @@
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
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FilterStackTraceFrameRule = void 0;
16
+ const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
17
+ const Utils_1 = __importDefault(require("../../Utils"));
18
+ /**
19
+ * stack trace frames as memory leaks
20
+ */
21
+ class FilterStackTraceFrameRule {
22
+ filter(_config, node) {
23
+ return Utils_1.default.isStackTraceFrame(node)
24
+ ? BaseLeakFilter_rule_1.LeakDecision.LEAK
25
+ : BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
26
+ }
27
+ }
28
+ exports.FilterStackTraceFrameRule = FilterStackTraceFrameRule;
@@ -0,0 +1,20 @@
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
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { MemLabConfig } from '../../Config';
11
+ import type { IHeapNode } from '../../Types';
12
+ import { ILeakObjectFilterRule, LeakDecision } from '../BaseLeakFilter.rule';
13
+ /**
14
+ * trivial nodes are not reported as memory leaks
15
+ */
16
+ export declare class FilterTrivialNodeRule implements ILeakObjectFilterRule {
17
+ filter(config: MemLabConfig, node: IHeapNode): LeakDecision;
18
+ protected isTrivialNode(node: IHeapNode): boolean;
19
+ }
20
+ //# sourceMappingURL=FilterTrivialNode.rule.d.ts.map
@@ -0,0 +1,33 @@
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
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FilterTrivialNodeRule = void 0;
16
+ const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
17
+ const Utils_1 = __importDefault(require("../../Utils"));
18
+ /**
19
+ * trivial nodes are not reported as memory leaks
20
+ */
21
+ class FilterTrivialNodeRule {
22
+ filter(config, node) {
23
+ return this.isTrivialNode(node)
24
+ ? BaseLeakFilter_rule_1.LeakDecision.NOT_LEAK
25
+ : BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
26
+ }
27
+ isTrivialNode(node) {
28
+ return (node.type === 'number' ||
29
+ Utils_1.default.isStringNode(node) ||
30
+ node.type === 'hidden');
31
+ }
32
+ }
33
+ exports.FilterTrivialNodeRule = FilterTrivialNodeRule;
@@ -0,0 +1,20 @@
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
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { MemLabConfig } from '../../Config';
11
+ import type { IHeapNode } from '../../Types';
12
+ import { ILeakObjectFilterRule, LeakDecision } from '../BaseLeakFilter.rule';
13
+ /**
14
+ * mark React FiberNodes without a React Fiber Root as memory leaks
15
+ */
16
+ export declare class FilterUnmountedFiberNodeRule implements ILeakObjectFilterRule {
17
+ filter(config: MemLabConfig, node: IHeapNode): LeakDecision;
18
+ protected checkDetachedFiberNode(config: MemLabConfig, node: IHeapNode): boolean;
19
+ }
20
+ //# sourceMappingURL=FilterUnmountedFiberNode.rule.d.ts.map
@@ -0,0 +1,37 @@
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
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FilterUnmountedFiberNodeRule = void 0;
16
+ const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
17
+ const Utils_1 = __importDefault(require("../../Utils"));
18
+ /**
19
+ * mark React FiberNodes without a React Fiber Root as memory leaks
20
+ */
21
+ class FilterUnmountedFiberNodeRule {
22
+ filter(config, node) {
23
+ if (this.checkDetachedFiberNode(config, node)) {
24
+ return BaseLeakFilter_rule_1.LeakDecision.LEAK;
25
+ }
26
+ return BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
27
+ }
28
+ checkDetachedFiberNode(config, node) {
29
+ if (!config.detectFiberNodeLeak ||
30
+ !Utils_1.default.isFiberNode(node) ||
31
+ Utils_1.default.hasHostRoot(node)) {
32
+ return false;
33
+ }
34
+ return !Utils_1.default.isNodeDominatedByDeletionsArray(node);
35
+ }
36
+ }
37
+ exports.FilterUnmountedFiberNodeRule = FilterUnmountedFiberNodeRule;
@@ -25,6 +25,7 @@ export default class NormalizedTrace {
25
25
  private static diffTraces;
26
26
  static diffClusters(newClusters: TraceCluster[], existingClusters: TraceCluster[]): TraceClusterDiff;
27
27
  static clusterLeakTraces(leakTraces: LeakTrace[]): Record<string, string>;
28
+ static filterClusters(clusters: TraceCluster[]): TraceCluster[];
28
29
  static clusterPaths(paths: LeakTracePathItem[], snapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb, option?: {
29
30
  strategy?: IClusterStrategy;
30
31
  }): TraceCluster[];
@@ -171,6 +171,16 @@ class NormalizedTrace {
171
171
  }, {});
172
172
  return labaledLeakTraces;
173
173
  }
174
+ static filterClusters(clusters) {
175
+ if (Config_1.default.clusterRetainedSizeThreshold <= 0) {
176
+ return clusters;
177
+ }
178
+ return clusters.filter(cluster => {
179
+ var _a;
180
+ return ((_a = cluster.retainedSize) !== null && _a !== void 0 ? _a : Infinity) >
181
+ Config_1.default.clusterRetainedSizeThreshold;
182
+ });
183
+ }
174
184
  static clusterPaths(paths, snapshot, aggregateDominatorMetrics, option = {}) {
175
185
  Console_1.default.overwrite('Clustering leak traces');
176
186
  if (paths.length === 0) {
@@ -192,7 +202,7 @@ class NormalizedTrace {
192
202
  // cluster traces
193
203
  const { allClusters } = NormalizedTrace.diffTraces(traces, [], option);
194
204
  // construct TraceCluster from clustering result
195
- const clusters = allClusters.map((traces) => {
205
+ let clusters = allClusters.map((traces) => {
196
206
  const cluster = {
197
207
  path: traceToPathMap.get(traces[0]),
198
208
  count: traces.length,
@@ -205,6 +215,7 @@ class NormalizedTrace {
205
215
  this.calculateClusterRetainedSize(cluster, snapshot, aggregateDominatorMetrics);
206
216
  return cluster;
207
217
  });
218
+ clusters = NormalizedTrace.filterClusters(clusters);
208
219
  clusters.sort((c1, c2) => { var _a, _b; return ((_a = c2.retainedSize) !== null && _a !== void 0 ? _a : 0) - ((_b = c1.retainedSize) !== null && _b !== void 0 ? _b : 0); });
209
220
  Console_1.default.midLevel(`MemLab found ${clusters.length} leak(s)`);
210
221
  return clusters;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memlab/core",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "license": "MIT",
5
5
  "description": "memlab core libraries",
6
6
  "author": "Liang Gong <lgong@fb.com>",
@@ -56,6 +56,7 @@
56
56
  "directory": "packages/core"
57
57
  },
58
58
  "scripts": {
59
+ "preinstall": "export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true",
59
60
  "build-pkg": "tsc",
60
61
  "test-pkg": "jest .",
61
62
  "clean-pkg": "rm -rf ./dist && rm -rf ./node_modules && rm -f ./tsconfig.tsbuildinfo"