Socket
Socket
Sign inDemoInstall

@memlab/core

Package Overview
Dependencies
Maintainers
3
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@memlab/core - npm Package Compare versions

Comparing version 1.1.9 to 1.1.10

2

dist/lib/Config.d.ts

@@ -209,3 +209,3 @@ /**

get browserBinaryPath(): string;
set reportLeaksInTimers(flag: boolean);
set reportLeaksInTimers(shouldReport: boolean);
get reportLeaksInTimers(): boolean;

@@ -212,0 +212,0 @@ setDevice(deviceName: string, options?: {

@@ -53,3 +53,3 @@ "use strict";

this._isFullRun = false;
this._reportLeaksInTimers = false;
this._reportLeaksInTimers = true;
this._deviceManualOverridden = false;

@@ -317,3 +317,3 @@ this._timerNodes = ['Pending activities'];

const config = new MemLabConfig();
// do not consider objects kept alive by timers as leaks
// consider objects kept alive by timers as leaks
config.reportLeaksInTimers = true;

@@ -401,7 +401,4 @@ // assign configuration to console manager

}
set reportLeaksInTimers(flag) {
if (typeof flag !== 'boolean') {
return;
}
if (flag) {
set reportLeaksInTimers(shouldReport) {
if (shouldReport) {
this.removeFromSet(this.nodeNameBlockList, this._timerNodes);

@@ -414,3 +411,3 @@ this.removeFromSet(this.edgeNameBlockList, this._timerEdges);

}
this._reportLeaksInTimers = flag;
this._reportLeaksInTimers = shouldReport;
}

@@ -417,0 +414,0 @@ get reportLeaksInTimers() {

@@ -7,4 +7,4 @@ /**

*
* @emails oncall+ws_labs
* @format
* @oncall ws_labs
*/

@@ -11,0 +11,0 @@ import type { AnyValue, IHeapSnapshot } from '../Types';

@@ -8,4 +8,4 @@ "use strict";

*
* @emails oncall+ws_labs
* @format
* @oncall ws_labs
*/

@@ -12,0 +12,0 @@ Object.defineProperty(exports, "__esModule", { value: true });

@@ -44,2 +44,10 @@ /**

}>;
/**
* Given a set of heap object ids, cluster them based on the similarity
* of their retainer traces and return a
* @param leakedNodeIds
* @param snapshot
* @returns
*/
clusterHeapObjects(objectIds: HeapNodeIdSet, snapshot: IHeapSnapshot): TraceCluster[];
serializeClusterUpdate(clusters: TraceCluster[], options?: {

@@ -46,0 +54,0 @@ reclusterOnly?: boolean;

@@ -650,2 +650,3 @@ /**

});
Console_1.default.midLevel(`MemLab found ${clusters.length} leak(s)`);
yield this.serializeClusterUpdate(clusters);

@@ -662,2 +663,32 @@ if (Config_1.default.logUnclassifiedClusters) {

}
/**
* Given a set of heap object ids, cluster them based on the similarity
* of their retainer traces and return a
* @param leakedNodeIds
* @param snapshot
* @returns
*/
clusterHeapObjects(objectIds, snapshot) {
const finder = this.preparePathFinder(snapshot);
const paths = [];
let i = 0;
// analysis for each node
Utils_1.default.applyToNodes(objectIds, snapshot, node => {
if (++i % 11 === 0) {
Console_1.default.overwrite(`progress: ${i} / ${objectIds.size} @${node.id}`);
}
// BFS search for path from the leaked node to GC roots
const p = finder.getPathToGCRoots(snapshot, node);
if (p) {
paths.push(p);
}
}, { reverse: true });
// cluster traces from the current run
const clusters = TraceBucket_1.default.clusterPaths(paths, snapshot, this.aggregateDominatorMetrics, {
strategy: Config_1.default.isMLClustering
? new MLTraceSimilarityStrategy_1.default()
: undefined,
});
return clusters;
}
serializeClusterUpdate(clusters, options = {}) {

@@ -664,0 +695,0 @@ return __awaiter(this, void 0, void 0, function* () {

@@ -1231,3 +1231,3 @@ /**

stop: boolean;
}>;
}> | void;
/**

@@ -1234,0 +1234,0 @@ * An `IHeapNode` instance represents a JS heap object in a heap snapshot.

@@ -25,2 +25,3 @@ /**

declare function isPendingActivityNode(node: IHeapNode): boolean;
declare function isDOMNodeIncomplete(node: IHeapNode): boolean;
declare function isRootNode(node: IHeapNode, opt?: AnyOptions): boolean;

@@ -175,2 +176,3 @@ declare function isDirectPropEdge(edge: IHeapEdge): boolean;

isDocumentDOMTreesRoot: typeof isDocumentDOMTreesRoot;
isDOMNodeIncomplete: typeof isDOMNodeIncomplete;
isEssentialEdge: typeof isEssentialEdge;

@@ -177,0 +179,0 @@ isFiberNode: typeof isFiberNode;

@@ -215,2 +215,13 @@ "use strict";

}
// check the node against a curated list of known HTML Elements
// the list may be incomplete
function isDOMNodeIncomplete(node) {
let name = node.name;
const pattern = /^HTML.*Element$/;
const detachedPrefix = 'Detached ';
if (name.startsWith(detachedPrefix)) {
name = name.substring(detachedPrefix.length);
}
return pattern.test(name);
}
function isRootNode(node, opt = {}) {

@@ -362,6 +373,7 @@ if (!node) {

}
// given a set of nodes S, return a subset S' where
// given a set of nodes S, return a minimal subset S' where
// no nodes are dominated by nodes in S
function getConditionalDominatorIds(ids, snapshot, condCb) {
const dominatorIds = new Set();
const fullDominatorIds = new Set();
// set all node ids

@@ -371,2 +383,3 @@ applyToNodes(ids, snapshot, node => {

dominatorIds.add(node.id);
fullDominatorIds.add(node.id);
}

@@ -383,3 +396,3 @@ });

}
if (dominatorIds.has(cur.id)) {
if (fullDominatorIds.has(cur.id)) {
dominatorIds.delete(node.id);

@@ -1740,2 +1753,3 @@ break;

isDocumentDOMTreesRoot,
isDOMNodeIncomplete,
isEssentialEdge,

@@ -1742,0 +1756,0 @@ isFiberNode,

@@ -391,6 +391,14 @@ "use strict";

const toNode = edge.toNode;
return (Config_1.default.hideBrowserLeak &&
(Utils_1.default.isBlinkRootNode(fromNode) ||
Utils_1.default.isPendingActivityNode(fromNode)) &&
Utils_1.default.isDetachedDOMNode(toNode));
const isDetachedNode = Utils_1.default.isDetachedDOMNode(toNode);
if (Config_1.default.hideBrowserLeak &&
Utils_1.default.isBlinkRootNode(fromNode) &&
isDetachedNode) {
return true;
}
if (!Config_1.default.reportLeaksInTimers &&
Utils_1.default.isPendingActivityNode(fromNode) &&
isDetachedNode) {
return true;
}
return false;
}

@@ -415,5 +423,16 @@ shouldTraverseEdge(edge, options = {}) {

}
if (Config_1.default.nodeNameBlockList.has(edge.toNode.name)) {
return true;
}
if (Config_1.default.nodeNameBlockList.has(edge.fromNode.name)) {
return true;
}
return false;
}
isLessPreferableEdge(edge) {
// pending activities -> DOM element is less preferrable
if (Utils_1.default.isPendingActivityNode(edge.fromNode) &&
Utils_1.default.isDOMNodeIncomplete(edge.toNode)) {
return true;
}
return Config_1.default.edgeNameGreyList.has(String(edge.name_or_index));

@@ -420,0 +439,0 @@ }

@@ -214,4 +214,5 @@ "use strict";

let clusters = allClusters.map((traces) => {
const representativeTrace = traces[0];
const cluster = {
path: traceToPathMap.get(traces[0]),
path: traceToPathMap.get(representativeTrace),
count: traces.length,

@@ -221,2 +222,7 @@ snapshot,

};
// add representative object id if there is one
const lastNode = representativeTrace[representativeTrace.length - 1];
if ('id' in lastNode) {
cluster.id = lastNode.id;
}
traces.forEach((trace) => {

@@ -230,3 +236,2 @@ NormalizedTrace.addLeakedNodeToCluster(cluster, traceToPathMap.get(trace));

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); });
Console_1.default.midLevel(`MemLab found ${clusters.length} leak(s)`);
return clusters;

@@ -233,0 +238,0 @@ }

{
"name": "@memlab/core",
"version": "1.1.9",
"version": "1.1.10",
"license": "MIT",

@@ -5,0 +5,0 @@ "description": "memlab core libraries",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc