@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.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -1
- package/dist/lib/Config.d.ts +2 -0
- package/dist/lib/Config.js +9 -0
- package/dist/lib/FileManager.d.ts +3 -0
- package/dist/lib/FileManager.js +10 -1
- package/dist/lib/HeapAnalyzer.d.ts +5 -1
- package/dist/lib/HeapAnalyzer.js +33 -21
- package/dist/lib/RunInfoUtils.d.ts +39 -0
- package/dist/lib/RunInfoUtils.js +86 -0
- package/dist/lib/Types.d.ts +7 -2
- package/dist/lib/Utils.d.ts +25 -19
- package/dist/lib/Utils.js +90 -148
- package/dist/lib/charts/MemoryBarChart.d.ts +1 -0
- package/dist/lib/charts/MemoryBarChart.js +18 -3
- package/dist/lib/trace-filters/BaseTraceFilter.rule.d.ts +29 -0
- package/dist/lib/trace-filters/BaseTraceFilter.rule.js +22 -0
- package/dist/lib/trace-filters/LeakTraceFilter.d.ts +20 -0
- package/dist/lib/trace-filters/LeakTraceFilter.js +37 -0
- package/dist/lib/trace-filters/TraceFilterRuleList.d.ts +13 -0
- package/dist/lib/trace-filters/TraceFilterRuleList.js +33 -0
- package/dist/lib/trace-filters/rules/FilterAttachedDOMToDetachedDOMTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterAttachedDOMToDetachedDOMTrace.rule.js +55 -0
- package/dist/lib/trace-filters/rules/FilterDOMNodeChainTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterDOMNodeChainTrace.rule.js +41 -0
- package/dist/lib/trace-filters/rules/FilterHermesTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterHermesTrace.rule.js +29 -0
- package/dist/lib/trace-filters/rules/FilterInternalNodeTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterInternalNodeTrace.rule.js +57 -0
- package/dist/lib/trace-filters/rules/FilterPendingActivitiesTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterPendingActivitiesTrace.rule.js +62 -0
- package/dist/lib/trace-filters/rules/FilterShadowRootTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterShadowRootTrace.rule.js +44 -0
- package/dist/lib/trace-filters/rules/FilterStyleEngineTrace.rule.d.ts +15 -0
- package/dist/lib/trace-filters/rules/FilterStyleEngineTrace.rule.js +49 -0
- package/dist/logger/LeakClusterLogger.js +1 -0
- package/dist/paths/TraceFinder.js +16 -2
- package/dist/trace-cluster/TraceBucket.d.ts +1 -1
- package/dist/trace-cluster/TraceBucket.js +7 -3
- package/dist/trace-cluster/strategies/TraceSimilarityStrategy.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
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.FilterDOMNodeChainTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
19
|
+
class FilterDOMNodeChainTraceRule {
|
|
20
|
+
filter(p, options = {}) {
|
|
21
|
+
var _a;
|
|
22
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
23
|
+
// if the path consists of only DOM native nodes/elements
|
|
24
|
+
if (curConfig.hideBrowserLeak && isDOMNodeChain(p)) {
|
|
25
|
+
return BaseTraceFilter_rule_1.TraceDecision.NOT_INSIGHTFUL;
|
|
26
|
+
}
|
|
27
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.FilterDOMNodeChainTraceRule = FilterDOMNodeChainTraceRule;
|
|
31
|
+
function isDOMNodeChain(path) {
|
|
32
|
+
let p = path;
|
|
33
|
+
// all the reference chain consists of DOM elements/nodes
|
|
34
|
+
while (p && p.node) {
|
|
35
|
+
if (!Utils_1.default.isRootNode(p.node) && !Utils_1.default.isDOMNodeIncomplete(p.node)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
p = p.next;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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 { LeakTracePathItem } from '../../Types';
|
|
11
|
+
import { ILeakTraceFilterRule, LeakTraceFilterOptions, TraceDecision } from '../BaseTraceFilter.rule';
|
|
12
|
+
export declare class FilterHermesTraceRule implements ILeakTraceFilterRule {
|
|
13
|
+
filter(_p: LeakTracePathItem, options?: LeakTraceFilterOptions): TraceDecision;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=FilterHermesTrace.rule.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
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.FilterHermesTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
18
|
+
class FilterHermesTraceRule {
|
|
19
|
+
filter(_p, options = {}) {
|
|
20
|
+
var _a;
|
|
21
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
22
|
+
// do not filter out paths when analyzing Hermes snapshots
|
|
23
|
+
if (curConfig.jsEngine === 'hermes') {
|
|
24
|
+
return BaseTraceFilter_rule_1.TraceDecision.INSIGHTFUL;
|
|
25
|
+
}
|
|
26
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.FilterHermesTraceRule = FilterHermesTraceRule;
|
|
@@ -0,0 +1,15 @@
|
|
|
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 { LeakTracePathItem } from '../../Types';
|
|
11
|
+
import { ILeakTraceFilterRule, LeakTraceFilterOptions, TraceDecision } from '../BaseTraceFilter.rule';
|
|
12
|
+
export declare class FilterInternalNodeTraceRule implements ILeakTraceFilterRule {
|
|
13
|
+
filter(p: LeakTracePathItem, options?: LeakTraceFilterOptions): TraceDecision;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=FilterInternalNodeTrace.rule.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
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.FilterInternalNodeTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
19
|
+
class FilterInternalNodeTraceRule {
|
|
20
|
+
filter(p, options = {}) {
|
|
21
|
+
var _a;
|
|
22
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
23
|
+
// if the path has pattern: Window -> [InternalNode]+ -> DetachedElement
|
|
24
|
+
if (curConfig.hideBrowserLeak && internalNodeRetainsDetachedElement(p)) {
|
|
25
|
+
return BaseTraceFilter_rule_1.TraceDecision.NOT_INSIGHTFUL;
|
|
26
|
+
}
|
|
27
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.FilterInternalNodeTraceRule = FilterInternalNodeTraceRule;
|
|
31
|
+
// check if the path has pattern:
|
|
32
|
+
// Window -> [InternalNode | Text]+ -> DetachedElement
|
|
33
|
+
function internalNodeRetainsDetachedElement(path) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
if (!path) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
let p = path;
|
|
39
|
+
// GC root is not Window
|
|
40
|
+
if (!p.node || !p.node.name.startsWith('Window')) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
p = p.next;
|
|
44
|
+
// Window is not poining to InternalNode
|
|
45
|
+
if (!p || !p.node || p.node.name !== 'InternalNode') {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// skip the rest InternalNode
|
|
49
|
+
while (((_a = p.node) === null || _a === void 0 ? void 0 : _a.name) === 'InternalNode' || ((_b = p.node) === null || _b === void 0 ? void 0 : _b.name) === 'Text') {
|
|
50
|
+
p = p.next;
|
|
51
|
+
if (!p) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// check if the node is a detached element
|
|
56
|
+
return p && Utils_1.default.isDetachedDOMNode(p.node);
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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 { LeakTracePathItem } from '../../Types';
|
|
11
|
+
import { ILeakTraceFilterRule, LeakTraceFilterOptions, TraceDecision } from '../BaseTraceFilter.rule';
|
|
12
|
+
export declare class FilterPendingActivitiesTraceRule implements ILeakTraceFilterRule {
|
|
13
|
+
filter(p: LeakTracePathItem, options?: LeakTraceFilterOptions): TraceDecision;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=FilterPendingActivitiesTrace.rule.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
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.FilterPendingActivitiesTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
19
|
+
class FilterPendingActivitiesTraceRule {
|
|
20
|
+
filter(p, options = {}) {
|
|
21
|
+
var _a;
|
|
22
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
23
|
+
// if the path has pattern: Pending activitiies -> DetachedElement
|
|
24
|
+
if (curConfig.hideBrowserLeak &&
|
|
25
|
+
pendingActivitiesRetainsDetachedElementChain(p)) {
|
|
26
|
+
return BaseTraceFilter_rule_1.TraceDecision.NOT_INSIGHTFUL;
|
|
27
|
+
}
|
|
28
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.FilterPendingActivitiesTraceRule = FilterPendingActivitiesTraceRule;
|
|
32
|
+
function pendingActivitiesRetainsDetachedElementChain(path) {
|
|
33
|
+
let p = path;
|
|
34
|
+
// find the Pending activities
|
|
35
|
+
while (p && p.node && !Utils_1.default.isPendingActivityNode(p.node)) {
|
|
36
|
+
p = p.next;
|
|
37
|
+
if (!p) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
p = p.next;
|
|
42
|
+
if (!p || !p.node) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// Scan the rest of the trace, if the following check is met,
|
|
46
|
+
// the leak trace is considered as not suitable for debugging:
|
|
47
|
+
// If the scanner encounters an object o on the
|
|
48
|
+
// rest of the leak trace, where o is neither a detached DOM node nor a
|
|
49
|
+
// Fiber Node and if the scanner didn't hit a detached DOM node first
|
|
50
|
+
while (p && p.node) {
|
|
51
|
+
if (Utils_1.default.isDetachedDOMNode(p.node)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (!Utils_1.default.isDOMInternalNode(p.node) &&
|
|
55
|
+
!Utils_1.default.isDetachedDOMNode(p.node) &&
|
|
56
|
+
!Utils_1.default.isFiberNode(p.node)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
p = p.next;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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 { LeakTracePathItem } from '../../Types';
|
|
11
|
+
import { ILeakTraceFilterRule, LeakTraceFilterOptions, TraceDecision } from '../BaseTraceFilter.rule';
|
|
12
|
+
export declare class FilterShadowRootTraceRule implements ILeakTraceFilterRule {
|
|
13
|
+
filter(p: LeakTracePathItem, options?: LeakTraceFilterOptions): TraceDecision;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=FilterShadowRootTrace.rule.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
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.FilterShadowRootTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
19
|
+
class FilterShadowRootTraceRule {
|
|
20
|
+
filter(p, options = {}) {
|
|
21
|
+
var _a;
|
|
22
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
23
|
+
// if the path has pattern: ShadowRoot -> DetachedElement
|
|
24
|
+
if (curConfig.hideBrowserLeak && shadowRootRetainsDetachedElement(p)) {
|
|
25
|
+
return BaseTraceFilter_rule_1.TraceDecision.NOT_INSIGHTFUL;
|
|
26
|
+
}
|
|
27
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.FilterShadowRootTraceRule = FilterShadowRootTraceRule;
|
|
31
|
+
// check if the path has pattern: ShadowRoot -> DetachedElement
|
|
32
|
+
function shadowRootRetainsDetachedElement(path) {
|
|
33
|
+
let p = path;
|
|
34
|
+
// find the ShadowRoot
|
|
35
|
+
while (p && p.node && p.node.name !== 'ShadowRoot') {
|
|
36
|
+
p = p.next;
|
|
37
|
+
if (!p) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
p = p.next;
|
|
42
|
+
// check if the node is a detached element
|
|
43
|
+
return !!p && Utils_1.default.isDetachedDOMNode(p.node);
|
|
44
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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 { LeakTracePathItem } from '../../Types';
|
|
11
|
+
import { ILeakTraceFilterRule, LeakTraceFilterOptions, TraceDecision } from '../BaseTraceFilter.rule';
|
|
12
|
+
export declare class FilterStyleEngineTraceRule implements ILeakTraceFilterRule {
|
|
13
|
+
filter(p: LeakTracePathItem, options?: LeakTraceFilterOptions): TraceDecision;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=FilterStyleEngineTrace.rule.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
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.FilterStyleEngineTraceRule = void 0;
|
|
16
|
+
const Config_1 = __importDefault(require("../../Config"));
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
const BaseTraceFilter_rule_1 = require("../BaseTraceFilter.rule");
|
|
19
|
+
class FilterStyleEngineTraceRule {
|
|
20
|
+
filter(p, options = {}) {
|
|
21
|
+
var _a;
|
|
22
|
+
const curConfig = (_a = options.config) !== null && _a !== void 0 ? _a : Config_1.default;
|
|
23
|
+
// if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
|
|
24
|
+
if (curConfig.hideBrowserLeak && styleEngineRetainsDetachedElement(p)) {
|
|
25
|
+
return BaseTraceFilter_rule_1.TraceDecision.NOT_INSIGHTFUL;
|
|
26
|
+
}
|
|
27
|
+
return BaseTraceFilter_rule_1.TraceDecision.MAYBE_INSIGHTFUL;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.FilterStyleEngineTraceRule = FilterStyleEngineTraceRule;
|
|
31
|
+
// check if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
|
|
32
|
+
function styleEngineRetainsDetachedElement(path) {
|
|
33
|
+
let p = path;
|
|
34
|
+
// find the StyleEngine
|
|
35
|
+
while (p && p.node && p.node.name !== 'StyleEngine') {
|
|
36
|
+
p = p.next;
|
|
37
|
+
if (!p) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
p = p.next;
|
|
42
|
+
// StyleEngine is not poining to InternalNode
|
|
43
|
+
if (!p || !p.node || p.node.name !== 'InternalNode') {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
p = p.next;
|
|
47
|
+
// check if the InternalNode is pointing to a detached element
|
|
48
|
+
return !!p && Utils_1.default.isDetachedDOMNode(p.node);
|
|
49
|
+
}
|
|
@@ -187,6 +187,7 @@ class LeakClusterLogger {
|
|
|
187
187
|
leak_trace_summary: trace.getTraceSummary(),
|
|
188
188
|
interaction_vector: interactionVector,
|
|
189
189
|
meta_data: JSON.stringify({
|
|
190
|
+
extraRunInfo: Utils_1.default.mapToObject(Config_1.default.extraRunInfoMap),
|
|
190
191
|
browser_info: BrowserInfo_1.default,
|
|
191
192
|
visit_plan: tabsOrder,
|
|
192
193
|
trace_record: TraceBucket_1.default.pathToTrace(cluster.path),
|
|
@@ -428,9 +428,23 @@ class TraceFinder {
|
|
|
428
428
|
return false;
|
|
429
429
|
}
|
|
430
430
|
isLessPreferableEdge(edge) {
|
|
431
|
+
const fromNode = edge.fromNode;
|
|
432
|
+
const toNode = edge.toNode;
|
|
431
433
|
// pending activities -> DOM element is less preferrable
|
|
432
|
-
if (Utils_1.default.isPendingActivityNode(
|
|
433
|
-
Utils_1.default.isDOMNodeIncomplete(
|
|
434
|
+
if (Utils_1.default.isPendingActivityNode(fromNode) &&
|
|
435
|
+
Utils_1.default.isDOMNodeIncomplete(toNode)) {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
// detached DOM node -> non-detached DOM node is less preferable
|
|
439
|
+
if (Utils_1.default.isDetachedDOMNode(fromNode) &&
|
|
440
|
+
Utils_1.default.isDOMNodeIncomplete(toNode) &&
|
|
441
|
+
!Utils_1.default.isDetachedDOMNode(toNode)) {
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
// non-detached DOM node -> detached DOM node is less preferable
|
|
445
|
+
if (Utils_1.default.isDOMNodeIncomplete(fromNode) &&
|
|
446
|
+
!Utils_1.default.isDetachedDOMNode(fromNode) &&
|
|
447
|
+
Utils_1.default.isDetachedDOMNode(toNode)) {
|
|
434
448
|
return true;
|
|
435
449
|
}
|
|
436
450
|
return Config_1.default.edgeNameGreyList.has(String(edge.name_or_index));
|
|
@@ -37,7 +37,7 @@ export default class NormalizedTrace {
|
|
|
37
37
|
private static buildTraceToPathMap;
|
|
38
38
|
private static pushLeakPathToCluster;
|
|
39
39
|
private static initEmptyCluster;
|
|
40
|
-
static clusterControlTreatmentPaths(
|
|
40
|
+
static clusterControlTreatmentPaths(leakPathsFromControlRuns: LeakTracePathItem[][], controlSnapshots: IHeapSnapshot[], treatmentPaths: LeakTracePathItem[], treatmentSnapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb, option?: {
|
|
41
41
|
strategy?: IClusterStrategy;
|
|
42
42
|
}): ControlTreatmentClusterResult;
|
|
43
43
|
static generateUnClassifiedClusters(paths: LeakTracePathItem[], snapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb): TraceCluster[];
|
|
@@ -308,19 +308,21 @@ class NormalizedTrace {
|
|
|
308
308
|
leakedNodeIds: new Set(),
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
|
-
static clusterControlTreatmentPaths(
|
|
311
|
+
static clusterControlTreatmentPaths(leakPathsFromControlRuns, controlSnapshots, treatmentPaths, treatmentSnapshot, aggregateDominatorMetrics, option = {}) {
|
|
312
312
|
const result = {
|
|
313
313
|
controlOnlyClusters: [],
|
|
314
314
|
treatmentOnlyClusters: [],
|
|
315
315
|
hybridClusters: [],
|
|
316
316
|
};
|
|
317
317
|
Console_1.default.overwrite('Clustering leak traces');
|
|
318
|
-
|
|
318
|
+
const totalControlPaths = leakPathsFromControlRuns.reduce((count, leakPaths) => count + leakPaths.length, 0);
|
|
319
|
+
if (totalControlPaths === 0 && treatmentPaths.length === 0) {
|
|
319
320
|
Console_1.default.midLevel('No leaks found');
|
|
320
321
|
return result;
|
|
321
322
|
}
|
|
322
323
|
// sample paths if there are too many
|
|
323
|
-
|
|
324
|
+
const flattenedLeakPathsFromControlRuns = leakPathsFromControlRuns.reduce((arr, leakPaths) => [...arr, ...leakPaths], []);
|
|
325
|
+
const controlPaths = this.samplePaths(flattenedLeakPathsFromControlRuns);
|
|
324
326
|
treatmentPaths = this.samplePaths(treatmentPaths);
|
|
325
327
|
// build control trace to control path map
|
|
326
328
|
const controlTraceToPathMap = NormalizedTrace.buildTraceToPathMap(controlPaths);
|
|
@@ -330,6 +332,8 @@ class NormalizedTrace {
|
|
|
330
332
|
const treatmentTraces = Array.from(treatmentTraceToPathMap.keys());
|
|
331
333
|
// cluster traces from both the control group and the treatment group
|
|
332
334
|
const { allClusters } = NormalizedTrace.diffTraces([...controlTraces, ...treatmentTraces], [], option);
|
|
335
|
+
// pick one of the control heap snapshots
|
|
336
|
+
const controlSnapshot = controlSnapshots[0];
|
|
333
337
|
// construct TraceCluster from clustering result
|
|
334
338
|
allClusters.forEach((traces) => {
|
|
335
339
|
var _a, _b;
|