@memlab/core 1.1.6 → 1.1.10
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/__tests__/parser/HeapParser.test.d.ts +1 -1
- package/dist/__tests__/parser/HeapParser.test.js +3 -3
- package/dist/__tests__/parser/NodeHeap.test.d.ts +1 -1
- package/dist/__tests__/parser/NodeHeap.test.js +6 -6
- package/dist/__tests__/parser/StringNode.test.d.ts +1 -1
- package/dist/__tests__/parser/StringNode.test.js +2 -2
- package/dist/__tests__/parser/traverse/HeapNodeTraverse.test.d.ts +1 -1
- package/dist/__tests__/parser/traverse/HeapNodeTraverse.test.js +3 -3
- package/dist/__tests__/utils/utils.test.d.ts +1 -1
- package/dist/__tests__/utils/utils.test.js +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -3
- package/dist/lib/BaseOption.d.ts +1 -1
- package/dist/lib/BaseOption.js +1 -1
- package/dist/lib/BrowserInfo.d.ts +1 -1
- package/dist/lib/BrowserInfo.js +1 -1
- package/dist/lib/Config.d.ts +8 -2
- package/dist/lib/Config.js +23 -12
- package/dist/lib/Console.d.ts +1 -1
- package/dist/lib/Console.js +1 -1
- package/dist/lib/Constant.d.ts +1 -1
- package/dist/lib/Constant.js +1 -1
- package/dist/lib/FileManager.d.ts +1 -1
- package/dist/lib/FileManager.js +5 -3
- package/dist/lib/HeapAnalyzer.d.ts +9 -1
- package/dist/lib/HeapAnalyzer.js +51 -9
- package/dist/lib/HeapParser.d.ts +2 -2
- package/dist/lib/HeapParser.js +2 -2
- package/dist/lib/InternalValueSetter.d.ts +1 -1
- package/dist/lib/InternalValueSetter.js +1 -1
- package/dist/lib/NodeHeap.d.ts +35 -12
- package/dist/lib/NodeHeap.js +55 -24
- package/dist/lib/PackageInfoLoader.js +1 -1
- package/dist/lib/ProcessManager.d.ts +1 -1
- package/dist/lib/ProcessManager.js +1 -1
- package/dist/lib/Serializer.d.ts +1 -1
- package/dist/lib/Serializer.js +1 -1
- package/dist/lib/StringLoader.d.ts +2 -2
- package/dist/lib/StringLoader.js +2 -2
- package/dist/lib/Types.d.ts +51 -33
- package/dist/lib/Types.js +1 -1
- package/dist/lib/Utils.d.ts +3 -1
- package/dist/lib/Utils.js +71 -33
- package/dist/lib/heap-data/HeapEdge.d.ts +2 -2
- package/dist/lib/heap-data/HeapEdge.js +2 -2
- package/dist/lib/heap-data/HeapLocation.d.ts +2 -2
- package/dist/lib/heap-data/HeapLocation.js +2 -2
- package/dist/lib/heap-data/HeapNode.d.ts +3 -2
- package/dist/lib/heap-data/HeapNode.js +6 -2
- package/dist/lib/heap-data/HeapSnapshot.d.ts +3 -2
- package/dist/lib/heap-data/HeapSnapshot.js +6 -33
- package/dist/lib/heap-data/HeapStringNode.d.ts +2 -2
- package/dist/lib/heap-data/HeapStringNode.js +4 -2
- package/dist/lib/heap-data/HeapUtils.d.ts +2 -2
- package/dist/lib/heap-data/HeapUtils.js +2 -2
- package/dist/lib/heap-data/MemLabTagStore.d.ts +23 -0
- package/dist/lib/heap-data/MemLabTagStore.js +110 -0
- package/dist/lib/leak-filters/BaseLeakFilter.rule.d.ts +1 -1
- package/dist/lib/leak-filters/BaseLeakFilter.rule.js +1 -1
- package/dist/lib/leak-filters/LeakFilterRuleList.d.ts +1 -1
- package/dist/lib/leak-filters/LeakFilterRuleList.js +1 -1
- package/dist/lib/leak-filters/LeakObjectFilter.d.ts +1 -1
- package/dist/lib/leak-filters/LeakObjectFilter.js +1 -1
- package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterByExternalFilter.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterDetachedDOMElement.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterHermesNode.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterHermesNode.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterOverSizedNodeAsLeak.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterStackTraceFrame.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterTrivialNode.rule.js +1 -1
- package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.d.ts +1 -1
- package/dist/lib/leak-filters/rules/FilterUnmountedFiberNode.rule.js +1 -1
- package/dist/logger/LeakClusterLogger.d.ts +1 -1
- package/dist/logger/LeakClusterLogger.js +1 -1
- package/dist/logger/LeakTraceDetailsLogger.d.ts +1 -1
- package/dist/logger/LeakTraceDetailsLogger.js +1 -1
- package/dist/modes/BaseMode.d.ts +1 -1
- package/dist/modes/BaseMode.js +1 -1
- package/dist/modes/InteractionTestMode.d.ts +1 -1
- package/dist/modes/InteractionTestMode.js +1 -1
- package/dist/modes/MeasureMode.d.ts +1 -1
- package/dist/modes/MeasureMode.js +1 -1
- package/dist/modes/RunningModes.d.ts +1 -1
- package/dist/modes/RunningModes.js +1 -1
- package/dist/paths/TraceFinder.d.ts +1 -1
- package/dist/paths/TraceFinder.js +58 -40
- package/dist/trace-cluster/ClusterUtils.d.ts +1 -1
- package/dist/trace-cluster/ClusterUtils.js +1 -1
- package/dist/trace-cluster/ClusterUtilsHelper.d.ts +1 -1
- package/dist/trace-cluster/ClusterUtilsHelper.js +1 -1
- package/dist/trace-cluster/ClusteringHeuristics.d.ts +1 -1
- package/dist/trace-cluster/ClusteringHeuristics.js +1 -1
- package/dist/trace-cluster/EvalutationMetric.d.ts +1 -1
- package/dist/trace-cluster/EvalutationMetric.js +1 -1
- package/dist/trace-cluster/SequentialClustering.d.ts +17 -0
- package/dist/trace-cluster/SequentialClustering.js +47 -0
- package/dist/trace-cluster/TraceBucket.d.ts +2 -1
- package/dist/trace-cluster/TraceBucket.js +11 -3
- package/dist/trace-cluster/TraceElement.d.ts +3 -1
- package/dist/trace-cluster/TraceElement.js +7 -1
- package/dist/trace-cluster/strategies/MLTraceSimilarityStrategy.d.ts +1 -1
- package/dist/trace-cluster/strategies/MLTraceSimilarityStrategy.js +2 -2
- package/dist/trace-cluster/strategies/TraceAsClusterStrategy.d.ts +1 -1
- package/dist/trace-cluster/strategies/TraceAsClusterStrategy.js +1 -1
- package/dist/trace-cluster/strategies/TraceSimilarityStrategy.d.ts +1 -1
- package/dist/trace-cluster/strategies/TraceSimilarityStrategy.js +1 -1
- package/dist/trace-cluster/strategies/machine-learning/DistanceMatrix.d.ts +1 -1
- package/dist/trace-cluster/strategies/machine-learning/DistanceMatrix.js +1 -1
- package/dist/trace-cluster/strategies/machine-learning/HAC.d.ts +2 -2
- package/dist/trace-cluster/strategies/machine-learning/HAC.js +5 -7
- package/dist/trace-cluster/strategies/machine-learning/Ngram.d.ts +1 -1
- package/dist/trace-cluster/strategies/machine-learning/Ngram.js +1 -1
- package/dist/trace-cluster/strategies/machine-learning/TfidfVectorizer.d.ts +1 -1
- package/dist/trace-cluster/strategies/machine-learning/TfidfVectorizer.js +7 -3
- package/package.json +1 -1
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
|
-
|
|
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
|
}
|
|
@@ -212,14 +212,28 @@ function isPendingActivityNode(node) {
|
|
|
212
212
|
}
|
|
213
213
|
return node.type === 'synthetic' && node.name === 'Pending activities';
|
|
214
214
|
}
|
|
215
|
+
// check the node against a curated list of known HTML Elements
|
|
216
|
+
// the list may be incomplete
|
|
217
|
+
function isDOMNodeIncomplete(node) {
|
|
218
|
+
let name = node.name;
|
|
219
|
+
const pattern = /^HTML.*Element$/;
|
|
220
|
+
const detachedPrefix = 'Detached ';
|
|
221
|
+
if (name.startsWith(detachedPrefix)) {
|
|
222
|
+
name = name.substring(detachedPrefix.length);
|
|
223
|
+
}
|
|
224
|
+
return pattern.test(name);
|
|
225
|
+
}
|
|
215
226
|
function isRootNode(node, opt = {}) {
|
|
216
|
-
if (!node
|
|
227
|
+
if (!node) {
|
|
217
228
|
return false;
|
|
218
229
|
}
|
|
219
230
|
// consider Hermes snapshot GC roots
|
|
220
231
|
if (Config_1.default.jsEngine === 'hermes') {
|
|
221
232
|
return node.name === '(GC roots)' || node.name === '(GC Roots)';
|
|
222
233
|
}
|
|
234
|
+
if (node.id === 0 || node.id === 1) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
223
237
|
// the window object
|
|
224
238
|
if (node.type === 'native' && node.name.indexOf('Window') === 0) {
|
|
225
239
|
return true;
|
|
@@ -355,14 +369,16 @@ function getNodesIdSet(snapshot) {
|
|
|
355
369
|
});
|
|
356
370
|
return set;
|
|
357
371
|
}
|
|
358
|
-
// given a set of nodes S, return a subset S' where
|
|
372
|
+
// given a set of nodes S, return a minimal subset S' where
|
|
359
373
|
// no nodes are dominated by nodes in S
|
|
360
374
|
function getConditionalDominatorIds(ids, snapshot, condCb) {
|
|
361
375
|
const dominatorIds = new Set();
|
|
376
|
+
const fullDominatorIds = new Set();
|
|
362
377
|
// set all node ids
|
|
363
378
|
applyToNodes(ids, snapshot, node => {
|
|
364
379
|
if (condCb(node)) {
|
|
365
380
|
dominatorIds.add(node.id);
|
|
381
|
+
fullDominatorIds.add(node.id);
|
|
366
382
|
}
|
|
367
383
|
});
|
|
368
384
|
// traverse the dominators and remove the node
|
|
@@ -374,7 +390,7 @@ function getConditionalDominatorIds(ids, snapshot, condCb) {
|
|
|
374
390
|
if (visited.has(cur.id)) {
|
|
375
391
|
break;
|
|
376
392
|
}
|
|
377
|
-
if (
|
|
393
|
+
if (fullDominatorIds.has(cur.id)) {
|
|
378
394
|
dominatorIds.delete(node.id);
|
|
379
395
|
break;
|
|
380
396
|
}
|
|
@@ -390,7 +406,6 @@ function setFiberNodeAttribute(node, flag) {
|
|
|
390
406
|
if (!node || !isFiberNode(node)) {
|
|
391
407
|
return;
|
|
392
408
|
}
|
|
393
|
-
// eslint-disable-next-line no-bitwise
|
|
394
409
|
node.attributes |= flag;
|
|
395
410
|
}
|
|
396
411
|
function hasFiberNodeAttribute(node, flag) {
|
|
@@ -447,7 +462,6 @@ function filterNodesInPlace(idSet, snapshot, cb) {
|
|
|
447
462
|
function applyToNodes(idSet, snapshot, cb, options = {}) {
|
|
448
463
|
let ids = Array.from(idSet.keys());
|
|
449
464
|
if (options.shuffle) {
|
|
450
|
-
// eslint-disable-next-line fb-www/unsafe-math-random
|
|
451
465
|
ids.sort(() => Math.random() - 0.5);
|
|
452
466
|
}
|
|
453
467
|
else if (options.reverse) {
|
|
@@ -508,7 +522,6 @@ function loadScenario(filename) {
|
|
|
508
522
|
}
|
|
509
523
|
let scenario;
|
|
510
524
|
try {
|
|
511
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
512
525
|
scenario = require(filepath);
|
|
513
526
|
scenario = checkScenarioInstance(scenario);
|
|
514
527
|
if (scenario.name == null) {
|
|
@@ -534,6 +547,12 @@ function handleSnapshotError(e) {
|
|
|
534
547
|
}
|
|
535
548
|
function getSnapshotFromFile(filename, options) {
|
|
536
549
|
return __awaiter(this, void 0, void 0, function* () {
|
|
550
|
+
const heapConfig = Config_1.default.heapConfig;
|
|
551
|
+
if (heapConfig &&
|
|
552
|
+
heapConfig.currentHeapFile === filename &&
|
|
553
|
+
heapConfig.currentHeap) {
|
|
554
|
+
return heapConfig.currentHeap;
|
|
555
|
+
}
|
|
537
556
|
Console_1.default.overwrite('parsing ' + filename + ' ...');
|
|
538
557
|
let ret = null;
|
|
539
558
|
try {
|
|
@@ -812,7 +831,6 @@ function loadRunMetaInfo(metaFile = undefined) {
|
|
|
812
831
|
try {
|
|
813
832
|
const content = fs_1.default.readFileSync(file, 'UTF-8');
|
|
814
833
|
return JSON.parse(content);
|
|
815
|
-
// eslint-disable-next-line fb-www/no-unused-catch-bindings
|
|
816
834
|
}
|
|
817
835
|
catch (_) {
|
|
818
836
|
throw haltOrThrow('Run info missing. Please make sure `memlab run` is complete.');
|
|
@@ -1271,9 +1289,23 @@ function getSnapshotDirForAnalysis() {
|
|
|
1271
1289
|
return dir;
|
|
1272
1290
|
}
|
|
1273
1291
|
function getSingleSnapshotFileForAnalysis() {
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1292
|
+
let path = null;
|
|
1293
|
+
// if an external snapshot file is specified
|
|
1294
|
+
if (Config_1.default.useExternalSnapshot &&
|
|
1295
|
+
Config_1.default.externalSnapshotFilePaths.length > 0) {
|
|
1296
|
+
path =
|
|
1297
|
+
Config_1.default.externalSnapshotFilePaths[Config_1.default.externalSnapshotFilePaths.length - 1];
|
|
1298
|
+
// if running in interactive heap analysis mode
|
|
1299
|
+
}
|
|
1300
|
+
else if (Config_1.default.heapConfig &&
|
|
1301
|
+
Config_1.default.heapConfig.isCliInteractiveMode &&
|
|
1302
|
+
Config_1.default.heapConfig.currentHeapFile) {
|
|
1303
|
+
path = Config_1.default.heapConfig.currentHeapFile;
|
|
1304
|
+
// search for snapshot labeled as baseline, target, or final
|
|
1305
|
+
}
|
|
1306
|
+
else {
|
|
1307
|
+
path = getSnapshotFilePathWithTabType(/(final)|(target)|(baseline)/);
|
|
1308
|
+
}
|
|
1277
1309
|
return resolveSnapshotFilePath(path);
|
|
1278
1310
|
}
|
|
1279
1311
|
function getSnapshotFilePath(tab) {
|
|
@@ -1286,7 +1318,7 @@ function getSnapshotFilePath(tab) {
|
|
|
1286
1318
|
}
|
|
1287
1319
|
return Config_1.default.externalSnapshotFilePaths[tab.idx - 1];
|
|
1288
1320
|
}
|
|
1289
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
1321
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1290
1322
|
function equalOrMatch(v1, v2) {
|
|
1291
1323
|
const t1 = typeof v1;
|
|
1292
1324
|
const t2 = typeof v2;
|
|
@@ -1319,7 +1351,8 @@ function isMeaningfulNode(node) {
|
|
|
1319
1351
|
if (!node) {
|
|
1320
1352
|
return false;
|
|
1321
1353
|
}
|
|
1322
|
-
|
|
1354
|
+
const nodeName = node.name;
|
|
1355
|
+
if (Config_1.default.nodeNameBlockList.has(nodeName)) {
|
|
1323
1356
|
return false;
|
|
1324
1357
|
}
|
|
1325
1358
|
if (isFiberNode(node)) {
|
|
@@ -1330,13 +1363,13 @@ function isMeaningfulNode(node) {
|
|
|
1330
1363
|
}
|
|
1331
1364
|
// More details in https://github.com/ChromeDevTools/devtools-frontend
|
|
1332
1365
|
// under front_end/heap_snapshot_worker/HeapSnapshot.ts
|
|
1333
|
-
if (
|
|
1366
|
+
if (nodeName === 'system / NativeContext') {
|
|
1334
1367
|
return false;
|
|
1335
1368
|
}
|
|
1336
|
-
if (
|
|
1369
|
+
if (nodeName === 'system / SourcePositionTableWithFrameCache') {
|
|
1337
1370
|
return false;
|
|
1338
1371
|
}
|
|
1339
|
-
if (
|
|
1372
|
+
if (nodeName === '(map descriptors)') {
|
|
1340
1373
|
return false;
|
|
1341
1374
|
}
|
|
1342
1375
|
if (node.type === 'code') {
|
|
@@ -1351,44 +1384,49 @@ function isMeaningfulEdge(edge, options = {}) {
|
|
|
1351
1384
|
if (source.id === node.id) {
|
|
1352
1385
|
return false;
|
|
1353
1386
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1387
|
+
const edgeNameOrIndex = edge.name_or_index;
|
|
1388
|
+
if (typeof edgeNameOrIndex === 'string' &&
|
|
1389
|
+
Config_1.default.edgeNameBlockList.has(edgeNameOrIndex)) {
|
|
1356
1390
|
return false;
|
|
1357
1391
|
}
|
|
1392
|
+
const edgeType = edge.type;
|
|
1358
1393
|
// shortcut edge may be meaningful edges
|
|
1359
1394
|
// --forceUpdate (variable)---> [native_bind]
|
|
1360
1395
|
// --bound_argument_0 (shortcut)---> [FiberNode]
|
|
1361
|
-
if (
|
|
1396
|
+
if (edgeType === 'weak' /* || edge.type === 'shortcut' */) {
|
|
1362
1397
|
return false;
|
|
1363
1398
|
}
|
|
1364
1399
|
if (options.excludeWeakMapEdge && isWeakMapEdgeToKey(edge)) {
|
|
1365
1400
|
return false;
|
|
1366
1401
|
}
|
|
1367
|
-
|
|
1402
|
+
const nodeIndex = node.nodeIndex;
|
|
1403
|
+
if (options.visited && options.visited[nodeIndex]) {
|
|
1368
1404
|
return false;
|
|
1369
1405
|
}
|
|
1370
|
-
if (options.queued && options.queued[
|
|
1406
|
+
if (options.queued && options.queued[nodeIndex]) {
|
|
1371
1407
|
return false;
|
|
1372
1408
|
}
|
|
1373
|
-
|
|
1409
|
+
const nodeType = node.type;
|
|
1410
|
+
if (!options.includeString && nodeType === 'string') {
|
|
1374
1411
|
return false;
|
|
1375
1412
|
}
|
|
1376
|
-
if (
|
|
1413
|
+
if (edgeType === 'internal' && edgeNameOrIndex === 'code') {
|
|
1377
1414
|
return false;
|
|
1378
1415
|
}
|
|
1379
1416
|
// More details about the following three special cases are available
|
|
1380
1417
|
// in https://github.com/ChromeDevTools/devtools-frontend
|
|
1381
1418
|
// under front_end/heap_snapshot_worker/HeapSnapshot.ts
|
|
1382
|
-
if (
|
|
1419
|
+
if (edgeType === 'hidden' && edgeNameOrIndex === 'sloppy_function_map') {
|
|
1383
1420
|
return false;
|
|
1384
1421
|
}
|
|
1385
|
-
|
|
1422
|
+
const nodeName = node.name;
|
|
1423
|
+
if (edgeType === 'hidden' && nodeName === 'system / NativeContext') {
|
|
1386
1424
|
return false;
|
|
1387
1425
|
}
|
|
1388
1426
|
// In v8, (map descriptors) are fixed-length descriptors arrays used
|
|
1389
1427
|
// to hold JS descriptors.
|
|
1390
|
-
if (
|
|
1391
|
-
const index =
|
|
1428
|
+
if (edgeType === 'array' && nodeName === '(map descriptors)') {
|
|
1429
|
+
const index = edgeNameOrIndex;
|
|
1392
1430
|
// only elements at particular indexes of (map descriptors) are holding
|
|
1393
1431
|
// representative references to objects.
|
|
1394
1432
|
if (index >= 2 || (typeof index === 'number' && index % 3 === 1)) {
|
|
@@ -1401,12 +1439,12 @@ function isMeaningfulEdge(edge, options = {}) {
|
|
|
1401
1439
|
if (Config_1.default.jsEngine === 'hermes' && isDirectPropEdge(edge)) {
|
|
1402
1440
|
return false;
|
|
1403
1441
|
}
|
|
1404
|
-
if (Config_1.default.ignoreInternalNode &&
|
|
1442
|
+
if (Config_1.default.ignoreInternalNode && nodeName.includes('InternalNode')) {
|
|
1405
1443
|
return false;
|
|
1406
1444
|
}
|
|
1407
1445
|
if (Config_1.default.ignoreDevToolsConsoleLeak) {
|
|
1408
|
-
|
|
1409
|
-
|
|
1446
|
+
if (typeof edgeNameOrIndex === 'string' &&
|
|
1447
|
+
edgeNameOrIndex.includes('DevTools console')) {
|
|
1410
1448
|
return false;
|
|
1411
1449
|
}
|
|
1412
1450
|
}
|
|
@@ -1421,7 +1459,6 @@ function isURLEqual(url1, url2) {
|
|
|
1421
1459
|
try {
|
|
1422
1460
|
u1 = new URL(url1);
|
|
1423
1461
|
u2 = new URL(url2);
|
|
1424
|
-
// eslint-disable-next-line fb-www/no-unused-catch-bindings
|
|
1425
1462
|
}
|
|
1426
1463
|
catch (_e) {
|
|
1427
1464
|
return false;
|
|
@@ -1709,6 +1746,7 @@ exports.default = {
|
|
|
1709
1746
|
isDetachedDOMNode,
|
|
1710
1747
|
isDirectPropEdge,
|
|
1711
1748
|
isDocumentDOMTreesRoot,
|
|
1749
|
+
isDOMNodeIncomplete,
|
|
1712
1750
|
isEssentialEdge,
|
|
1713
1751
|
isFiberNode,
|
|
1714
1752
|
isFiberNodeDeletionsEdge,
|
|
@@ -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) {
|
|
@@ -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 { IHeapLocation } 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
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -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 { IHeapNode, IHeapEdge, Nullable, EdgeIterationCallback, Predicator, IHeapStringNode } from '../Types';
|
|
12
12
|
import type HeapSnapshot from './HeapSnapshot';
|
|
@@ -36,6 +36,7 @@ export default class HeapNode implements IHeapNode {
|
|
|
36
36
|
findReferrers(predicate: Predicator<IHeapEdge>): IHeapEdge[];
|
|
37
37
|
get referrers(): HeapEdge[];
|
|
38
38
|
forEachReferrer(callback: EdgeIterationCallback): void;
|
|
39
|
+
get hasPathEdge(): boolean;
|
|
39
40
|
get pathEdge(): Nullable<HeapEdge>;
|
|
40
41
|
set pathEdge(edge: Nullable<HeapEdge>);
|
|
41
42
|
get nodeIndex(): number;
|
|
@@ -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) {
|
|
@@ -189,6 +189,10 @@ class HeapNode {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
+
get hasPathEdge() {
|
|
193
|
+
const heapSnapshot = this.heapSnapshot;
|
|
194
|
+
return heapSnapshot._nodeIdxHasPathEdge[this.idx] !== 0;
|
|
195
|
+
}
|
|
192
196
|
get pathEdge() {
|
|
193
197
|
const heapSnapshot = this.heapSnapshot;
|
|
194
198
|
if (heapSnapshot._nodeIdxHasPathEdge[this.idx] === 0) {
|
|
@@ -4,14 +4,15 @@
|
|
|
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 { IHeapNode, IHeapNodes, IHeapEdges, IHeapSnapshot, HeapNodeTypes, HeapEdgeTypes, HeapSnapshotMeta, RawHeapSnapshot, NumericDictionary, Nullable } from '../Types';
|
|
12
12
|
import HeapNode from './HeapNode';
|
|
13
13
|
export default class HeapSnapshot implements IHeapSnapshot {
|
|
14
14
|
snapshot: RawHeapSnapshot;
|
|
15
|
+
isProcessed: boolean;
|
|
15
16
|
nodes: IHeapNodes;
|
|
16
17
|
_nodeCount: number;
|
|
17
18
|
edges: IHeapEdges;
|
|
@@ -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) {
|
|
@@ -18,11 +18,13 @@ const Console_1 = __importDefault(require("../Console"));
|
|
|
18
18
|
const HeapNode_1 = __importDefault(require("./HeapNode"));
|
|
19
19
|
const HeapEdge_1 = __importDefault(require("./HeapEdge"));
|
|
20
20
|
const HeapUtils_1 = require("./HeapUtils");
|
|
21
|
+
const MemLabTagStore_1 = __importDefault(require("./MemLabTagStore"));
|
|
21
22
|
const EMPTY_UINT8_ARRAY = new Uint8Array(0);
|
|
22
23
|
const EMPTY_UINT32_ARRAY = new Uint32Array(0);
|
|
23
24
|
class HeapSnapshot {
|
|
24
25
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
26
|
constructor(snapshot, _options = {}) {
|
|
27
|
+
this.isProcessed = false;
|
|
26
28
|
this._nodeCount = -1;
|
|
27
29
|
this._edgeCount = -1;
|
|
28
30
|
this._nodeId2NodeIdx = {};
|
|
@@ -98,7 +100,7 @@ class HeapSnapshot {
|
|
|
98
100
|
forEachTraceable(cb) {
|
|
99
101
|
for (let i = 0; i < this.length; i++) {
|
|
100
102
|
const node = this.get(i);
|
|
101
|
-
if (!node.
|
|
103
|
+
if (!node.hasPathEdge) {
|
|
102
104
|
continue;
|
|
103
105
|
}
|
|
104
106
|
const ret = cb(node, i);
|
|
@@ -158,36 +160,7 @@ class HeapSnapshot {
|
|
|
158
160
|
return detected;
|
|
159
161
|
}
|
|
160
162
|
hasObjectWithTag(tag) {
|
|
161
|
-
|
|
162
|
-
let tagStore = null;
|
|
163
|
-
this.nodes.forEach((node) => {
|
|
164
|
-
if (node.name === 'MemLabTaggedStore' && node.type === 'object') {
|
|
165
|
-
tagStore = node;
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
if (tagStore == null) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
const store = tagStore;
|
|
173
|
-
// get tagStore.taggedObjects
|
|
174
|
-
const taggedObjects = store.getReferenceNode('taggedObjects', 'property');
|
|
175
|
-
if (taggedObjects == null) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
// get taggedObjects[tag]
|
|
179
|
-
const weakSet = taggedObjects.getReferenceNode(tag, 'property');
|
|
180
|
-
if (weakSet == null) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
// get weakSet.table
|
|
184
|
-
const table = weakSet.getReferenceNode('table');
|
|
185
|
-
if (table == null) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
// check if the table has any weak reference to any object
|
|
189
|
-
const ref = table.findAnyReference((edge) => edge.type === 'weak' && edge.toNode.name !== 'system / Oddball');
|
|
190
|
-
return ref != null;
|
|
163
|
+
return MemLabTagStore_1.default.hasObjectWithTag(this, tag);
|
|
191
164
|
}
|
|
192
165
|
getNodeById(id) {
|
|
193
166
|
if (!(id in this._nodeId2NodeIdx)) {
|
|
@@ -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 { IHeapStringNode } 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) {
|
|
@@ -35,6 +35,8 @@ class HeapStringNode extends HeapNode_1.default {
|
|
|
35
35
|
if (parentNode == null) {
|
|
36
36
|
throw (0, HeapUtils_1.throwError)(new Error('broken sliced string'));
|
|
37
37
|
}
|
|
38
|
+
// sliced string in heap snapshot doesn't include
|
|
39
|
+
// the start index and the end index, so this may be inaccurate
|
|
38
40
|
return parentNode.stringValue;
|
|
39
41
|
}
|
|
40
42
|
return this.name;
|
|
@@ -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
|
export declare const NodeDetachState: {
|
|
12
12
|
Unknown: number;
|
|
@@ -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
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,23 @@
|
|
|
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 ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import type { AnyValue, IHeapSnapshot } from '../Types';
|
|
11
|
+
declare type AnyObject = Record<AnyValue, AnyValue>;
|
|
12
|
+
/** @internal */
|
|
13
|
+
export default class MemLabTaggedStore {
|
|
14
|
+
taggedObjects: Record<string, WeakSet<AnyObject>>;
|
|
15
|
+
private constructor();
|
|
16
|
+
private static instance;
|
|
17
|
+
readonly id: string;
|
|
18
|
+
static getInstance(): MemLabTaggedStore;
|
|
19
|
+
static tagObject<T extends object>(o: T, tag: string): void;
|
|
20
|
+
static hasObjectWithTag(heap: IHeapSnapshot, tag: string): boolean;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=MemLabTagStore.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
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 ws_labs
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const __1 = require("../..");
|
|
13
|
+
let uindex = 1;
|
|
14
|
+
function getUniqueID() {
|
|
15
|
+
const randId = `${Math.random()}`;
|
|
16
|
+
return `${process.pid}-${Date.now()}-${randId}-${uindex++}`;
|
|
17
|
+
}
|
|
18
|
+
/** @internal */
|
|
19
|
+
class MemLabTaggedStore {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.id = getUniqueID();
|
|
22
|
+
this.taggedObjects = Object.create(null);
|
|
23
|
+
}
|
|
24
|
+
// make sure it's a singleton
|
|
25
|
+
static getInstance() {
|
|
26
|
+
if (!MemLabTaggedStore.instance) {
|
|
27
|
+
MemLabTaggedStore.instance = new MemLabTaggedStore();
|
|
28
|
+
}
|
|
29
|
+
return MemLabTaggedStore.instance;
|
|
30
|
+
}
|
|
31
|
+
// tag an object with a mark
|
|
32
|
+
static tagObject(o, tag) {
|
|
33
|
+
const store = MemLabTaggedStore.getInstance();
|
|
34
|
+
if (!store.taggedObjects[tag]) {
|
|
35
|
+
store.taggedObjects[tag] = new WeakSet();
|
|
36
|
+
}
|
|
37
|
+
store.taggedObjects[tag].add(o);
|
|
38
|
+
}
|
|
39
|
+
// check if any object in the heap snapshot has the mark
|
|
40
|
+
// tagged by this MemLabTaggedStore in this execution context
|
|
41
|
+
static hasObjectWithTag(heap, tag) {
|
|
42
|
+
const curContextTagStoreID = MemLabTaggedStore.getInstance().id;
|
|
43
|
+
let tagStore = null;
|
|
44
|
+
// get all MemLabTaggedStore instances in the heap snapshot
|
|
45
|
+
const stores = [];
|
|
46
|
+
heap.nodes.forEach((node) => {
|
|
47
|
+
if (node.name === 'MemLabTaggedStore' && node.type === 'object') {
|
|
48
|
+
stores.push(node);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// if no tag store found
|
|
52
|
+
if (stores.length === 0) {
|
|
53
|
+
return false;
|
|
54
|
+
// if there is only one store found
|
|
55
|
+
}
|
|
56
|
+
else if (stores.length === 1) {
|
|
57
|
+
tagStore = stores[0];
|
|
58
|
+
// if there are multiple MemLabTagStore instances
|
|
59
|
+
// found in the heap snapshot
|
|
60
|
+
}
|
|
61
|
+
else if (stores.length > 1) {
|
|
62
|
+
stores.forEach((node) => {
|
|
63
|
+
// in case multiple instances of MemLabTaggedStore exists
|
|
64
|
+
// in the heap snapshot, we need to make sure that the
|
|
65
|
+
// tag store is the one matching the current execution context
|
|
66
|
+
let storeID = '';
|
|
67
|
+
// match tag store id
|
|
68
|
+
node.forEachReference(edge => {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
if (edge.name_or_index === 'id' && edge.toNode.isString) {
|
|
71
|
+
storeID = (_b = (_a = edge.toNode.toStringNode()) === null || _a === void 0 ? void 0 : _a.stringValue) !== null && _b !== void 0 ? _b : '';
|
|
72
|
+
return { stop: true };
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
if (curContextTagStoreID === storeID) {
|
|
76
|
+
tagStore = node;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
if (tagStore == null) {
|
|
80
|
+
throw __1.utils.haltOrThrow('Multiple MemLabTagStore instances found in heap snapshot ' +
|
|
81
|
+
'when checking object tags, please make sure only one memlab ' +
|
|
82
|
+
'instance is running at a time and double check that memlab is ' +
|
|
83
|
+
'not running in Jest concurrent mode.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (tagStore == null) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const store = tagStore;
|
|
90
|
+
// get tagStore.taggedObjects
|
|
91
|
+
const taggedObjects = store.getReferenceNode('taggedObjects', 'property');
|
|
92
|
+
if (taggedObjects == null) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
// get taggedObjects[tag]
|
|
96
|
+
const weakSet = taggedObjects.getReferenceNode(tag, 'property');
|
|
97
|
+
if (weakSet == null) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
// get weakSet.table
|
|
101
|
+
const table = weakSet.getReferenceNode('table');
|
|
102
|
+
if (table == null) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
// check if the table has any weak reference to any object
|
|
106
|
+
const ref = table.findAnyReference((edge) => edge.type === 'weak' && edge.toNode.name !== 'system / Oddball');
|
|
107
|
+
return ref != null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.default = MemLabTaggedStore;
|
|
@@ -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 { MemLabConfig } from '../Config';
|
|
11
11
|
import type { HeapNodeIdSet, IHeapNode, IHeapSnapshot } from '../Types';
|