@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.
- package/dist/index.d.ts +17 -0
- package/dist/index.js +17 -0
- package/dist/lib/Config.d.ts +5 -2
- package/dist/lib/Config.js +9 -2
- package/dist/lib/FileManager.d.ts +2 -0
- package/dist/lib/FileManager.js +1 -0
- package/dist/lib/HeapAnalyzer.d.ts +2 -2
- package/dist/lib/HeapAnalyzer.js +27 -60
- package/dist/lib/InternalValueSetter.d.ts +2 -0
- package/dist/lib/InternalValueSetter.js +2 -0
- package/dist/lib/Types.d.ts +63 -6
- package/dist/lib/Utils.js +24 -1
- package/dist/lib/leak-filters/BaseLeakFilter.rule.d.ts +24 -0
- package/dist/lib/leak-filters/BaseLeakFilter.rule.js +22 -0
- package/dist/lib/leak-filters/LeakFilterRuleList.d.ts +13 -0
- package/dist/lib/leak-filters/LeakFilterRuleList.js +33 -0
- package/dist/lib/leak-filters/LeakObjectFilter.d.ts +19 -0
- package/dist/lib/leak-filters/LeakObjectFilter.js +36 -0
- package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.d.ts +19 -0
- package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.js +27 -0
- package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.d.ts +20 -0
- package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.js +40 -0
- package/dist/lib/leak-filters/rules/FilterHermesNode.rule.d.ts +16 -0
- package/dist/lib/leak-filters/rules/FilterHermesNode.rule.js +27 -0
- package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.d.ts +19 -0
- package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.js +27 -0
- package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.d.ts +19 -0
- package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.js +28 -0
- package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.d.ts +20 -0
- package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.js +33 -0
- package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.d.ts +20 -0
- package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.js +37 -0
- package/dist/trace-cluster/TraceBucket.d.ts +1 -0
- package/dist/trace-cluster/TraceBucket.js +12 -1
- package/package.json +2 -1
package/dist/lib/Types.d.ts
CHANGED
|
@@ -11,19 +11,30 @@ import { ParsedArgs } from 'minimist';
|
|
|
11
11
|
import type { LaunchOptions, Page } from 'puppeteer';
|
|
12
12
|
import type { ErrorHandling, MemLabConfig } from './Config';
|
|
13
13
|
export declare type AnyValue = any;
|
|
14
|
+
/** @internal */
|
|
14
15
|
export declare type RecordValue = string | number | boolean | null | RecordValue[] | {
|
|
15
16
|
[key: string]: RecordValue;
|
|
16
17
|
};
|
|
18
|
+
/** @internal */
|
|
17
19
|
export declare type Nullable<T> = T | null;
|
|
20
|
+
/** @internal */
|
|
18
21
|
export declare type Optional<T> = Nullable<T> | undefined;
|
|
22
|
+
/** @internal */
|
|
19
23
|
export declare type AnyRecord = Record<string, RecordValue>;
|
|
24
|
+
/** @internal */
|
|
20
25
|
export declare type AnyAyncFunction = (...args: AnyValue[]) => Promise<AnyValue>;
|
|
26
|
+
/** @internal */
|
|
21
27
|
export declare type AnyFunction = (...args: AnyValue[]) => AnyValue;
|
|
28
|
+
/** @internal */
|
|
22
29
|
export declare type AnyOptions = Record<string, unknown>;
|
|
30
|
+
/** @internal */
|
|
23
31
|
export declare type UnusedOptions = Record<string, never>;
|
|
32
|
+
/** @internal */
|
|
24
33
|
export declare type Command = [string, string[], AnyOptions];
|
|
25
34
|
export declare type Predicator<T> = (node: T) => boolean;
|
|
26
|
-
|
|
35
|
+
/** @internal */
|
|
36
|
+
export declare type HeapNodeIdSet = Set<number>;
|
|
37
|
+
/** @internal */
|
|
27
38
|
export declare type HaltOrThrowOptions = {
|
|
28
39
|
printErrorBeforeHalting?: boolean;
|
|
29
40
|
errorHandling?: ErrorHandling;
|
|
@@ -31,10 +42,12 @@ export declare type HaltOrThrowOptions = {
|
|
|
31
42
|
secondaryMessageToPrint?: string;
|
|
32
43
|
printCallback?: () => void;
|
|
33
44
|
};
|
|
45
|
+
/** @internal */
|
|
34
46
|
export declare type CLIOptions = {
|
|
35
47
|
cliArgs: ParsedArgs;
|
|
36
48
|
configFromOptions?: AnyRecord;
|
|
37
49
|
};
|
|
50
|
+
/** @internal */
|
|
38
51
|
export declare type XvfbType = {
|
|
39
52
|
start: (callback: (error: Error) => AnyValue | null) => void;
|
|
40
53
|
stop: (callback: (error: Error) => AnyValue | null) => void;
|
|
@@ -42,6 +55,7 @@ export declare type XvfbType = {
|
|
|
42
55
|
stopSync: () => void;
|
|
43
56
|
display: () => string;
|
|
44
57
|
};
|
|
58
|
+
/** @internal */
|
|
45
59
|
export declare type CLIArgs = {
|
|
46
60
|
verbose: boolean;
|
|
47
61
|
app: string;
|
|
@@ -71,11 +85,11 @@ export declare type CLIArgs = {
|
|
|
71
85
|
'local-puppeteer': boolean;
|
|
72
86
|
'snapshot-dir': string;
|
|
73
87
|
};
|
|
74
|
-
declare type
|
|
88
|
+
export declare type Cookies = Array<{
|
|
75
89
|
name: string;
|
|
76
90
|
value: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
91
|
+
}>;
|
|
92
|
+
/** @internal */
|
|
79
93
|
export interface IE2EScenarioSynthesizer {
|
|
80
94
|
getAppName(): string;
|
|
81
95
|
getOrigin(): Nullable<string>;
|
|
@@ -99,9 +113,11 @@ export interface IE2EScenarioSynthesizer {
|
|
|
99
113
|
getExtraOperationsForStep(_stepInfo: E2EStepInfo): E2EOperation[];
|
|
100
114
|
synthesis(baseline: string, target: string, intermediates: string[], options: E2ESynthesizerOptions): IE2EScenarioVisitPlan;
|
|
101
115
|
}
|
|
116
|
+
/** @internal */
|
|
102
117
|
export interface E2EScenarioSynthesizerConstructor {
|
|
103
118
|
new (config: Config): IE2EScenarioSynthesizer;
|
|
104
119
|
}
|
|
120
|
+
/** @internal */
|
|
105
121
|
export interface IRunningMode {
|
|
106
122
|
setConfig(config: Config): void;
|
|
107
123
|
beforeRunning(visitPlan: IE2EScenarioVisitPlan): void;
|
|
@@ -117,7 +133,9 @@ export interface IRunningMode {
|
|
|
117
133
|
getAdditionalMetrics(page: Page, tabInfo?: E2EStepInfo): Promise<E2EStepInfo['metrics']>;
|
|
118
134
|
postProcessData(visitPlan: IE2EScenarioVisitPlan): void;
|
|
119
135
|
}
|
|
136
|
+
/** @internal */
|
|
120
137
|
export declare type Config = MemLabConfig;
|
|
138
|
+
/** @internal */
|
|
121
139
|
export declare type QuickExperiment = {
|
|
122
140
|
universe: string;
|
|
123
141
|
experiment: string;
|
|
@@ -133,7 +151,7 @@ export declare type InteractionsCallback = (page: Page, args?: OperationArgs) =>
|
|
|
133
151
|
export interface IScenario {
|
|
134
152
|
name?: () => string;
|
|
135
153
|
app?: () => string;
|
|
136
|
-
cookies?: () =>
|
|
154
|
+
cookies?: () => Cookies;
|
|
137
155
|
url: () => string;
|
|
138
156
|
action?: InteractionsCallback;
|
|
139
157
|
back?: InteractionsCallback;
|
|
@@ -142,12 +160,14 @@ export interface IScenario {
|
|
|
142
160
|
beforeLeakFilter?: InitLeakFilterCallback;
|
|
143
161
|
leakFilter?: LeakFilterCallback;
|
|
144
162
|
}
|
|
163
|
+
/** @internal */
|
|
145
164
|
export declare type LeakTracePathItem = {
|
|
146
165
|
node?: IHeapNode;
|
|
147
166
|
edge?: IHeapEdge;
|
|
148
167
|
next?: LeakTracePathItem;
|
|
149
168
|
edgeRetainSize?: number;
|
|
150
169
|
};
|
|
170
|
+
/** @internal */
|
|
151
171
|
export declare type TraceCluster = {
|
|
152
172
|
id?: number;
|
|
153
173
|
path: LeakTracePathItem;
|
|
@@ -157,11 +177,13 @@ export declare type TraceCluster = {
|
|
|
157
177
|
leakedNodeIds?: HeapNodeIdSet;
|
|
158
178
|
clusterMetaInfo?: TraceClusterMetaInfo;
|
|
159
179
|
};
|
|
180
|
+
/** @internal */
|
|
160
181
|
export declare type TraceClusterDiff = {
|
|
161
182
|
staleClusters: TraceCluster[];
|
|
162
183
|
clustersToAdd: TraceCluster[];
|
|
163
184
|
allClusters: TraceCluster[][];
|
|
164
185
|
};
|
|
186
|
+
/** @internal */
|
|
165
187
|
export declare type LeakTraceElement = {
|
|
166
188
|
kind: string;
|
|
167
189
|
id?: number;
|
|
@@ -169,12 +191,15 @@ export declare type LeakTraceElement = {
|
|
|
169
191
|
name_or_index?: string | number;
|
|
170
192
|
type: string;
|
|
171
193
|
};
|
|
194
|
+
/** @internal */
|
|
172
195
|
export declare type LeakTrace = LeakTraceElement[];
|
|
196
|
+
/** @internal */
|
|
173
197
|
export declare type TraceDiff = {
|
|
174
198
|
staleClusters: LeakTrace[];
|
|
175
199
|
clustersToAdd: LeakTrace[];
|
|
176
200
|
allClusters: LeakTrace[][];
|
|
177
201
|
};
|
|
202
|
+
/** @internal */
|
|
178
203
|
export declare type TraceClusterMetaInfo = {
|
|
179
204
|
cluster_id: number;
|
|
180
205
|
creation_time: number;
|
|
@@ -189,14 +214,17 @@ export declare type TraceClusterMetaInfo = {
|
|
|
189
214
|
leak_trace_handle?: string;
|
|
190
215
|
meta_data: string;
|
|
191
216
|
};
|
|
217
|
+
/** @internal */
|
|
192
218
|
export interface E2EInteraction {
|
|
193
219
|
kind: string;
|
|
194
220
|
timeout?: number;
|
|
195
221
|
}
|
|
222
|
+
/** @internal */
|
|
196
223
|
export declare type E2EOperation = E2EInteraction & {
|
|
197
224
|
selector: string;
|
|
198
225
|
act(page: Page, opArgs?: OperationArgs): Promise<void>;
|
|
199
226
|
};
|
|
227
|
+
/** @internal */
|
|
200
228
|
export declare type E2ESynthesizerOptions = {
|
|
201
229
|
name?: string;
|
|
202
230
|
type?: string;
|
|
@@ -212,11 +240,14 @@ export declare type E2ESynthesizerOptions = {
|
|
|
212
240
|
gk_enable?: string[];
|
|
213
241
|
gk_disable?: string[];
|
|
214
242
|
};
|
|
243
|
+
/** @internal */
|
|
215
244
|
export interface IDataBuilder {
|
|
216
245
|
className: string;
|
|
217
246
|
state: Record<string, AnyValue>;
|
|
218
247
|
}
|
|
248
|
+
/** @internal */
|
|
219
249
|
export declare type CheckPageLoadCallback = (page: Page) => Promise<boolean>;
|
|
250
|
+
/** @internal */
|
|
220
251
|
export interface IE2EScenarioVisitPlan {
|
|
221
252
|
name: string;
|
|
222
253
|
appName: string;
|
|
@@ -230,6 +261,7 @@ export interface IE2EScenarioVisitPlan {
|
|
|
230
261
|
dataBuilder: Optional<IDataBuilder>;
|
|
231
262
|
isPageLoaded?: CheckPageLoadCallback;
|
|
232
263
|
}
|
|
264
|
+
/** @internal */
|
|
233
265
|
export declare type OperationArgs = {
|
|
234
266
|
isPageLoaded?: CheckPageLoadCallback;
|
|
235
267
|
showProgress?: boolean;
|
|
@@ -240,6 +272,7 @@ export declare type OperationArgs = {
|
|
|
240
272
|
warmup?: boolean;
|
|
241
273
|
noWaitAfterPageLoad?: boolean;
|
|
242
274
|
};
|
|
275
|
+
/** @internal */
|
|
243
276
|
export interface IE2EStepBasic {
|
|
244
277
|
name: string;
|
|
245
278
|
url: string;
|
|
@@ -252,6 +285,7 @@ export interface IE2EStepBasic {
|
|
|
252
285
|
interactions: E2EOperation | Array<E2EOperation | InteractionsCallback>;
|
|
253
286
|
postInteractions?: E2EOperation | Array<E2EOperation | InteractionsCallback>;
|
|
254
287
|
}
|
|
288
|
+
/** @internal */
|
|
255
289
|
export declare type E2EStepInfo = IE2EStepBasic & {
|
|
256
290
|
snapshot: boolean;
|
|
257
291
|
screenshot: boolean;
|
|
@@ -260,6 +294,7 @@ export declare type E2EStepInfo = IE2EStepBasic & {
|
|
|
260
294
|
delay?: number;
|
|
261
295
|
metrics: Record<string, number>;
|
|
262
296
|
};
|
|
297
|
+
/** @internal */
|
|
263
298
|
export interface IBrowserInfo {
|
|
264
299
|
_browserVersion: string;
|
|
265
300
|
_puppeteerConfig: LaunchOptions;
|
|
@@ -353,16 +388,27 @@ export interface IHeapNodes {
|
|
|
353
388
|
forEach(callback: (node: IHeapNode, index: number) => void | boolean): void;
|
|
354
389
|
forEachTraceable(callback: (node: IHeapNode, index: number) => void | boolean): void;
|
|
355
390
|
}
|
|
391
|
+
/** @internal */
|
|
356
392
|
export declare type HeapNodeFields = string[];
|
|
393
|
+
/** @internal */
|
|
357
394
|
export declare type HeapNodeTypes = string[];
|
|
395
|
+
/** @internal */
|
|
358
396
|
export declare type RawHeapNodeTypes = Array<HeapNodeTypes | string>;
|
|
397
|
+
/** @internal */
|
|
359
398
|
export declare type HeapEdgeFields = string[];
|
|
399
|
+
/** @internal */
|
|
360
400
|
export declare type HeapEdgeTypes = string[] | string;
|
|
401
|
+
/** @internal */
|
|
361
402
|
export declare type RawHeapEdgeTypes = Array<HeapEdgeTypes | string>;
|
|
403
|
+
/** @internal */
|
|
362
404
|
export declare type HeapTraceFunctionInfoFields = string[];
|
|
405
|
+
/** @internal */
|
|
363
406
|
export declare type HeapTraceNodeFields = string[];
|
|
407
|
+
/** @internal */
|
|
364
408
|
export declare type HeapSampleFields = string[];
|
|
409
|
+
/** @internal */
|
|
365
410
|
export declare type HeapLocationFields = string[];
|
|
411
|
+
/** @internal */
|
|
366
412
|
export declare type HeapSnapshotMeta = {
|
|
367
413
|
node_fields: HeapNodeFields;
|
|
368
414
|
node_types: RawHeapNodeTypes;
|
|
@@ -373,12 +419,14 @@ export declare type HeapSnapshotMeta = {
|
|
|
373
419
|
sample_fields: HeapSampleFields;
|
|
374
420
|
location_fields: HeapLocationFields;
|
|
375
421
|
};
|
|
422
|
+
/** @internal */
|
|
376
423
|
export declare type HeapSnapshotInfo = {
|
|
377
424
|
meta: HeapSnapshotMeta;
|
|
378
425
|
node_count: number;
|
|
379
426
|
edge_count: number;
|
|
380
427
|
trace_function_count: number;
|
|
381
428
|
};
|
|
429
|
+
/** @internal */
|
|
382
430
|
export declare type RawHeapSnapshot = {
|
|
383
431
|
snapshot: HeapSnapshotInfo;
|
|
384
432
|
nodes: number[];
|
|
@@ -389,12 +437,15 @@ export declare type RawHeapSnapshot = {
|
|
|
389
437
|
locations: number[];
|
|
390
438
|
strings: string[];
|
|
391
439
|
};
|
|
440
|
+
/** @internal */
|
|
392
441
|
export interface ISerializedInfo {
|
|
393
442
|
[key: string]: string | number | boolean | ISerializedInfo;
|
|
394
443
|
}
|
|
444
|
+
/** @internal */
|
|
395
445
|
export declare type NumericDictionary = {
|
|
396
446
|
[index: number]: number;
|
|
397
447
|
};
|
|
448
|
+
/** @internal */
|
|
398
449
|
export interface IOveralHeapInfo {
|
|
399
450
|
fiberNodeSize: number;
|
|
400
451
|
regularFiberNodeSize: number;
|
|
@@ -402,31 +453,37 @@ export interface IOveralHeapInfo {
|
|
|
402
453
|
alternateFiberNodeSize: number;
|
|
403
454
|
error: number;
|
|
404
455
|
}
|
|
456
|
+
/** @internal */
|
|
405
457
|
export interface IOveralLeakInfo extends Partial<IOveralHeapInfo> {
|
|
406
458
|
leakedSize: number;
|
|
407
459
|
leakedFiberNodeSize: number;
|
|
408
460
|
leakedAlternateFiberNodeSize: number;
|
|
409
461
|
}
|
|
462
|
+
/** @internal */
|
|
410
463
|
export interface IMemoryAnalystOptions {
|
|
411
464
|
snapshotDir?: string;
|
|
412
465
|
minSnapshots?: number;
|
|
413
466
|
}
|
|
467
|
+
/** @internal */
|
|
414
468
|
export interface IMemoryAnalystSnapshotDiff {
|
|
415
469
|
leakedHeapNodeIdSet: HeapNodeIdSet;
|
|
416
470
|
snapshot: IHeapSnapshot;
|
|
417
471
|
listOfLeakedHeapNodeIdSet: Array<HeapNodeIdSet>;
|
|
418
472
|
}
|
|
473
|
+
/** @internal */
|
|
419
474
|
export interface IMemoryAnalystHeapNodeLeakSummary extends Pick<IHeapNode, 'name' | 'type' | 'retainedSize'> {
|
|
420
475
|
count: number;
|
|
421
476
|
}
|
|
477
|
+
/** @internal */
|
|
422
478
|
export interface IMemoryAnalystHeapNodeReferrenceStat {
|
|
423
479
|
numberOfEdgesToNode: number;
|
|
424
480
|
source: IHeapNode;
|
|
425
481
|
edge: IHeapEdge;
|
|
426
482
|
}
|
|
483
|
+
/** @internal */
|
|
427
484
|
export interface IClusterStrategy {
|
|
428
485
|
diffTraces: (newLeakTraces: LeakTrace[], existingLeakTraces: LeakTrace[]) => TraceDiff;
|
|
429
486
|
}
|
|
487
|
+
/** @internal */
|
|
430
488
|
export declare type ErrorWithMessage = Pick<Error, 'message'>;
|
|
431
|
-
export {};
|
|
432
489
|
//# sourceMappingURL=Types.d.ts.map
|
package/dist/lib/Utils.js
CHANGED
|
@@ -356,7 +356,7 @@ function getNodesIdSet(snapshot) {
|
|
|
356
356
|
return set;
|
|
357
357
|
}
|
|
358
358
|
// given a set of nodes S, return a subset S' where
|
|
359
|
-
// no nodes are
|
|
359
|
+
// no nodes are dominated by nodes in S
|
|
360
360
|
function getConditionalDominatorIds(ids, snapshot, condCb) {
|
|
361
361
|
const dominatorIds = new Set();
|
|
362
362
|
// set all node ids
|
|
@@ -863,6 +863,10 @@ function isInterestingPath(p) {
|
|
|
863
863
|
if (Config_1.default.hideBrowserLeak && shadowRootRetainsDetachedElement(p)) {
|
|
864
864
|
return false;
|
|
865
865
|
}
|
|
866
|
+
// if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
|
|
867
|
+
if (Config_1.default.hideBrowserLeak && styleEngineRetainsDetachedElement(p)) {
|
|
868
|
+
return false;
|
|
869
|
+
}
|
|
866
870
|
return true;
|
|
867
871
|
}
|
|
868
872
|
// return true if the heap node represents JS object or closure
|
|
@@ -923,6 +927,25 @@ function shadowRootRetainsDetachedElement(path) {
|
|
|
923
927
|
// check if the node is a detached element
|
|
924
928
|
return !!p && isDetachedDOMNode(p.node);
|
|
925
929
|
}
|
|
930
|
+
// check if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
|
|
931
|
+
function styleEngineRetainsDetachedElement(path) {
|
|
932
|
+
let p = path;
|
|
933
|
+
// find the StyleEngine
|
|
934
|
+
while (p && p.node && p.node.name !== 'StyleEngine') {
|
|
935
|
+
p = p.next;
|
|
936
|
+
if (!p) {
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
p = p.next;
|
|
941
|
+
// StyleEngine is not poining to InternalNode
|
|
942
|
+
if (!p || !p.node || p.node.name !== 'InternalNode') {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
p = p.next;
|
|
946
|
+
// check if the InternalNode is pointing to a detached element
|
|
947
|
+
return !!p && isDetachedDOMNode(p.node);
|
|
948
|
+
}
|
|
926
949
|
function pathHasDetachedHTMLNode(path) {
|
|
927
950
|
if (!path) {
|
|
928
951
|
return false;
|
|
@@ -0,0 +1,24 @@
|
|
|
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 { HeapNodeIdSet, IHeapNode, IHeapSnapshot } from '../Types';
|
|
12
|
+
/**
|
|
13
|
+
* Every leak object filter rule needs to give a label
|
|
14
|
+
* to each object passed to the filter
|
|
15
|
+
*/
|
|
16
|
+
export declare enum LeakDecision {
|
|
17
|
+
LEAK = "leak",
|
|
18
|
+
MAYBE_LEAK = "maybe-leak",
|
|
19
|
+
NOT_LEAK = "not-leak"
|
|
20
|
+
}
|
|
21
|
+
export interface ILeakObjectFilterRule {
|
|
22
|
+
filter(config: MemLabConfig, node: IHeapNode, snapshot: IHeapSnapshot, leakedNodeIds: HeapNodeIdSet): LeakDecision;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=BaseLeakFilter.rule.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
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.LeakDecision = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* Every leak object filter rule needs to give a label
|
|
15
|
+
* to each object passed to the filter
|
|
16
|
+
*/
|
|
17
|
+
var LeakDecision;
|
|
18
|
+
(function (LeakDecision) {
|
|
19
|
+
LeakDecision["LEAK"] = "leak";
|
|
20
|
+
LeakDecision["MAYBE_LEAK"] = "maybe-leak";
|
|
21
|
+
LeakDecision["NOT_LEAK"] = "not-leak";
|
|
22
|
+
})(LeakDecision = exports.LeakDecision || (exports.LeakDecision = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
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 { ILeakObjectFilterRule } from './BaseLeakFilter.rule';
|
|
11
|
+
declare const _default: ILeakObjectFilterRule[];
|
|
12
|
+
export default _default;
|
|
13
|
+
//# sourceMappingURL=LeakFilterRuleList.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
|
+
const Constant_1 = __importDefault(require("../Constant"));
|
|
16
|
+
const InternalValueSetter_1 = require("../InternalValueSetter");
|
|
17
|
+
const FilterByExternalFilter_rule_1 = require("./rules/FilterByExternalFilter.rule");
|
|
18
|
+
const FilterDetachedDOMElement_rule_1 = require("./rules/FilterDetachedDOMElement.rule");
|
|
19
|
+
const FilterHermesNode_rule_1 = require("./rules/FilterHermesNode.rule");
|
|
20
|
+
const FilterOverSizedNodeAsLeak_rule_1 = require("./rules/FilterOverSizedNodeAsLeak.rule");
|
|
21
|
+
const FilterStackTraceFrame_rule_1 = require("./rules/FilterStackTraceFrame.rule");
|
|
22
|
+
const FilterTrivialNode_rule_1 = require("./rules/FilterTrivialNode.rule");
|
|
23
|
+
const FilterUnmountedFiberNode_rule_1 = require("./rules/FilterUnmountedFiberNode.rule");
|
|
24
|
+
const list = [
|
|
25
|
+
new FilterByExternalFilter_rule_1.FilterByExternalFilterRule(),
|
|
26
|
+
new FilterTrivialNode_rule_1.FilterTrivialNodeRule(),
|
|
27
|
+
new FilterHermesNode_rule_1.FilterHermesNodeRule(),
|
|
28
|
+
new FilterOverSizedNodeAsLeak_rule_1.FilterOverSizedNodeAsLeakRule(),
|
|
29
|
+
new FilterUnmountedFiberNode_rule_1.FilterUnmountedFiberNodeRule(),
|
|
30
|
+
new FilterDetachedDOMElement_rule_1.FilterDetachedDOMElementRule(),
|
|
31
|
+
new FilterStackTraceFrame_rule_1.FilterStackTraceFrameRule(),
|
|
32
|
+
];
|
|
33
|
+
exports.default = (0, InternalValueSetter_1.setInternalValue)(list, __filename, Constant_1.default.internalDir);
|
|
@@ -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 { HeapNodeIdSet, IHeapNode, IHeapSnapshot } from '../Types';
|
|
12
|
+
/**
|
|
13
|
+
* apply the leak object filter rules chain and decide
|
|
14
|
+
* if an object is a memory leak or not
|
|
15
|
+
*/
|
|
16
|
+
export declare class LeakObjectFilter {
|
|
17
|
+
filter(config: MemLabConfig, node: IHeapNode, snapshot: IHeapSnapshot, leakedNodeIds: HeapNodeIdSet): boolean;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=LeakObjectFilter.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
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.LeakObjectFilter = void 0;
|
|
16
|
+
const BaseLeakFilter_rule_1 = require("./BaseLeakFilter.rule");
|
|
17
|
+
const LeakFilterRuleList_1 = __importDefault(require("./LeakFilterRuleList"));
|
|
18
|
+
/**
|
|
19
|
+
* apply the leak object filter rules chain and decide
|
|
20
|
+
* if an object is a memory leak or not
|
|
21
|
+
*/
|
|
22
|
+
class LeakObjectFilter {
|
|
23
|
+
filter(config, node, snapshot, leakedNodeIds) {
|
|
24
|
+
for (const rule of LeakFilterRuleList_1.default) {
|
|
25
|
+
const decision = rule.filter(config, node, snapshot, leakedNodeIds);
|
|
26
|
+
if (decision === BaseLeakFilter_rule_1.LeakDecision.LEAK) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (decision === BaseLeakFilter_rule_1.LeakDecision.NOT_LEAK) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.LeakObjectFilter = LeakObjectFilter;
|
|
@@ -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 { HeapNodeIdSet, IHeapNode, IHeapSnapshot } from '../../Types';
|
|
12
|
+
import { ILeakObjectFilterRule, LeakDecision } from '../BaseLeakFilter.rule';
|
|
13
|
+
/**
|
|
14
|
+
* filter memory leaks defined by external leak filter
|
|
15
|
+
*/
|
|
16
|
+
export declare class FilterByExternalFilterRule implements ILeakObjectFilterRule {
|
|
17
|
+
filter(config: MemLabConfig, node: IHeapNode, snapshot: IHeapSnapshot, leakedNodeIds: HeapNodeIdSet): LeakDecision;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=FilterByExternalFilter.rule.d.ts.map
|
|
@@ -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.FilterByExternalFilterRule = void 0;
|
|
13
|
+
const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
|
|
14
|
+
/**
|
|
15
|
+
* filter memory leaks defined by external leak filter
|
|
16
|
+
*/
|
|
17
|
+
class FilterByExternalFilterRule {
|
|
18
|
+
filter(config, node, snapshot, leakedNodeIds) {
|
|
19
|
+
if (config.externalLeakFilter) {
|
|
20
|
+
return config.externalLeakFilter.leakFilter(node, snapshot, leakedNodeIds)
|
|
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.FilterByExternalFilterRule = FilterByExternalFilterRule;
|
|
@@ -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 detached DOM elements as memory leaks
|
|
15
|
+
*/
|
|
16
|
+
export declare class FilterDetachedDOMElementRule implements ILeakObjectFilterRule {
|
|
17
|
+
filter(_config: MemLabConfig, node: IHeapNode): LeakDecision;
|
|
18
|
+
protected checkDetachedFiberNode(config: MemLabConfig, node: IHeapNode): boolean;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=FilterDetachedDOMElement.rule.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
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.FilterDetachedDOMElementRule = void 0;
|
|
16
|
+
const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
/**
|
|
19
|
+
* mark detached DOM elements as memory leaks
|
|
20
|
+
*/
|
|
21
|
+
class FilterDetachedDOMElementRule {
|
|
22
|
+
filter(_config, node) {
|
|
23
|
+
const isDetached = Utils_1.default.isDetachedDOMNode(node, {
|
|
24
|
+
ignoreInternalNode: true,
|
|
25
|
+
});
|
|
26
|
+
if (isDetached) {
|
|
27
|
+
return BaseLeakFilter_rule_1.LeakDecision.LEAK;
|
|
28
|
+
}
|
|
29
|
+
return BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
|
|
30
|
+
}
|
|
31
|
+
checkDetachedFiberNode(config, node) {
|
|
32
|
+
if (!config.detectFiberNodeLeak ||
|
|
33
|
+
!Utils_1.default.isFiberNode(node) ||
|
|
34
|
+
Utils_1.default.hasHostRoot(node)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return !Utils_1.default.isNodeDominatedByDeletionsArray(node);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.FilterDetachedDOMElementRule = FilterDetachedDOMElementRule;
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
export declare class FilterHermesNodeRule implements ILeakObjectFilterRule {
|
|
14
|
+
filter(config: MemLabConfig, node: IHeapNode): LeakDecision;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=FilterHermesNode.rule.d.ts.map
|
|
@@ -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
|
+
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.FilterHermesNodeRule = void 0;
|
|
16
|
+
const BaseLeakFilter_rule_1 = require("../BaseLeakFilter.rule");
|
|
17
|
+
const Utils_1 = __importDefault(require("../../Utils"));
|
|
18
|
+
class FilterHermesNodeRule {
|
|
19
|
+
filter(config, node) {
|
|
20
|
+
// when analyzing hermes heap snapshots, filter Hermes internal objects
|
|
21
|
+
if (config.jsEngine === 'hermes' && Utils_1.default.isHermesInternalObject(node)) {
|
|
22
|
+
return BaseLeakFilter_rule_1.LeakDecision.NOT_LEAK;
|
|
23
|
+
}
|
|
24
|
+
return BaseLeakFilter_rule_1.LeakDecision.MAYBE_LEAK;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.FilterHermesNodeRule = FilterHermesNodeRule;
|
|
@@ -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
|
+
* trivial nodes are not reported as memory leaks
|
|
15
|
+
*/
|
|
16
|
+
export declare class FilterOverSizedNodeAsLeakRule implements ILeakObjectFilterRule {
|
|
17
|
+
filter(config: MemLabConfig, node: IHeapNode): LeakDecision;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=FilterOverSizedNodeAsLeak.rule.d.ts.map
|