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.20 to 1.1.21

dist/lib/RunInfoUtils.d.ts

2

dist/index.d.ts

@@ -29,2 +29,4 @@ /**

/** @internal */
export { default as runInfoUtils } from './lib/RunInfoUtils';
/** @internal */
export * from './lib/FileManager';

@@ -31,0 +33,0 @@ /** @internal */

5

dist/index.js

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

Object.defineProperty(exports, "__esModule", { value: true });
exports.TraceFinder = exports.MultiIterationSeqClustering = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.memoryBarChart = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
exports.TraceFinder = exports.MultiIterationSeqClustering = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.memoryBarChart = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.runInfoUtils = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
const path_1 = __importDefault(require("path"));

@@ -71,2 +71,5 @@ const PackageInfoLoader_1 = require("./lib/PackageInfoLoader");

/** @internal */
var RunInfoUtils_1 = require("./lib/RunInfoUtils");
Object.defineProperty(exports, "runInfoUtils", { enumerable: true, get: function () { return __importDefault(RunInfoUtils_1).default; } });
/** @internal */
__exportStar(require("./lib/FileManager"), exports);

@@ -73,0 +76,0 @@ /** @internal */

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

plotMemoryBarChart(options?: PlotMemoryOptions): void;
private isPlotDataValid;
private loadPlotDataFromTabsOrder;

@@ -15,0 +16,0 @@ private loadPlotDataFromWorkDir;

@@ -33,3 +33,3 @@ /**

}
if (plotData.length === 0) {
if (!this.isPlotDataValid(plotData)) {
if (Config_1.default.verbose) {

@@ -61,2 +61,17 @@ Console_1.default.warning('no memory usage data to plot');

}
isPlotDataValid(plotData) {
if (plotData.length === 0) {
return false;
}
let isEntryValueAllZero = true;
for (const entry of plotData) {
if (entry.length !== 2) {
return false;
}
if (entry[1] !== 0) {
isEntryValueAllZero = false;
}
}
return !isEntryValueAllZero;
}
loadPlotDataFromTabsOrder(tabsOrder) {

@@ -87,3 +102,3 @@ for (const tab of tabsOrder) {

// plot data for a single run
if (!options.controlWorkDir && !options.treatmentWorkDir) {
if (!options.controlWorkDirs && !options.treatmentWorkDir) {
return this.loadPlotDataFromWorkDir(options);

@@ -93,3 +108,3 @@ }

const controlPlotData = this.loadPlotDataFromWorkDir({
workDir: options.controlWorkDir,
workDir: options.controlWorkDirs && options.controlWorkDirs[0],
});

@@ -96,0 +111,0 @@ const testPlotData = this.loadPlotDataFromWorkDir({

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

externalCookiesFile: Optional<string>;
extraRunInfoMap: Map<string, string>;
heapConfig: Optional<IHeapConfig>;

@@ -229,2 +230,3 @@ puppeteerConfig: LaunchOptions & BrowserLaunchArgumentOptions & BrowserConnectOptions;

}): void;
setRunInfo(key: string, value: string): void;
private removeFromSet;

@@ -231,0 +233,0 @@ private addToSet;

@@ -179,2 +179,8 @@ "use strict";

this.seqClusteringIsRandomChunks = false;
// extra E2E run info (other than the fields defined in
// RunMetaInfo like app, interaction, browserInfo).
// Information saved in this map will be
// auto-serialized to run-meta.json when the file is saved
// and auto-deserialized from run-meta.json when the file is loaded
this.extraRunInfoMap = new Map();
}

@@ -511,2 +517,5 @@ // initialize configurable parameters

}
setRunInfo(key, value) {
this.extraRunInfoMap.set(key, value);
}
removeFromSet(set, list) {

@@ -513,0 +522,0 @@ for (const v of list) {

@@ -13,2 +13,4 @@ /**

/** @internal */
export declare function joinAndProcessDir(options: FileOption, ...args: AnyValue[]): string;
/** @internal */
export declare class FileManager {

@@ -79,2 +81,3 @@ private memlabConfigCache;

createDefaultVisitOrderMetaFile(options?: FileOption): void;
createDefaultVisitOrderMetaFileWithSingleSnapshot(options: FileOption | undefined, snapshotFile: string): void;
initDirs(config: MemLabConfig, options?: FileOption): void;

@@ -81,0 +84,0 @@ }

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

Object.defineProperty(exports, "__esModule", { value: true });
exports.FileManager = void 0;
exports.FileManager = exports.joinAndProcessDir = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));

@@ -23,2 +23,3 @@ const os_1 = __importDefault(require("os"));

const Utils_1 = __importDefault(require("./Utils"));
/** @internal */
function joinAndProcessDir(options, ...args) {

@@ -39,2 +40,3 @@ const filepath = path_1.default.join(...args);

}
exports.joinAndProcessDir = joinAndProcessDir;
/** @internal */

@@ -316,2 +318,5 @@ class FileManager {

isDirectory(file) {
if (!fs_extra_1.default.existsSync(file)) {
return false;
}
const stats = fs_extra_1.default.statSync(file);

@@ -363,2 +368,6 @@ return stats.isDirectory();

// First, get the meta file for leak detection in a single heap snapshot
this.createDefaultVisitOrderMetaFileWithSingleSnapshot(options, snapshotFile);
}
createDefaultVisitOrderMetaFileWithSingleSnapshot(options = FileManager.defaultFileOption, snapshotFile) {
const snapshotSeqMetaFile = this.getSnapshotSequenceMetaFile(options);
const codeDataDir = this.getCodeDataDir();

@@ -365,0 +374,0 @@ const singleSnapshotMetaFile = path_1.default.join(codeDataDir, 'visit-order-single-snapshot.json');

@@ -19,2 +19,6 @@ /**

};
declare type GetTraceOptions = {
workDir?: string;
printConsoleOnly?: boolean;
};
declare class MemoryAnalyst {

@@ -54,3 +58,3 @@ checkLeak(): Promise<ISerializedInfo[]>;

}): Promise<void>;
dumpPathByNodeId(leakedIdSet: HeapNodeIdSet, snapshot: IHeapSnapshot, nodeIdsInSnapshots: Array<HeapNodeIdSet>, id: number, pathLoaderFile: string, summaryFile: string, options?: WorkDirOptions): void;
dumpPathByNodeId(leakedIdSet: HeapNodeIdSet, snapshot: IHeapSnapshot, nodeIdsInSnapshots: Array<HeapNodeIdSet>, id: number, pathLoaderFile: string, summaryFile: string, options?: GetTraceOptions): void;
}

@@ -57,0 +61,0 @@ declare const _default: MemoryAnalyst;

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

const MLTraceSimilarityStrategy_1 = __importDefault(require("../trace-cluster/strategies/MLTraceSimilarityStrategy"));
const LeakTraceFilter_1 = require("./trace-filters/LeakTraceFilter");
class MemoryAnalyst {

@@ -48,5 +49,5 @@ checkLeak() {

return __awaiter(this, void 0, void 0, function* () {
const controlSnapshotDir = FileManager_1.default.getCurDataDir({
workDir: options.controlWorkDir,
});
const controlSnapshotDirs = options.controlWorkDirs.map(controlWorkDir => FileManager_1.default.getCurDataDir({
workDir: controlWorkDir,
}));
const treatmentSnapshotDir = FileManager_1.default.getCurDataDir({

@@ -56,3 +57,3 @@ workDir: options.treatmentWorkDir,

// check control working dir
Utils_1.default.checkSnapshots({ snapshotDir: controlSnapshotDir });
controlSnapshotDirs.forEach(controlSnapshotDir => Utils_1.default.checkSnapshots({ snapshotDir: controlSnapshotDir }));
// check treatment working dir

@@ -69,19 +70,24 @@ Utils_1.default.checkSnapshots({ snapshotDir: treatmentSnapshotDir });

Config_1.default.dumpNodeInfo = false;
// diff snapshots and get control raw paths
let snapshotDiff = yield this.diffSnapshots({
loadAllSnapshots: true,
workDir: options.controlWorkDir,
});
const controlLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.controlWorkDir });
const controlSnapshot = snapshotDiff.snapshot;
// diff snapshots from control dirs and get control raw paths array
const controlSnapshots = [];
const leakPathsFromControlRuns = [];
for (const controlWorkDir of options.controlWorkDirs) {
const snapshotDiff = yield this.diffSnapshots({
loadAllSnapshots: true,
workDir: controlWorkDir,
});
leakPathsFromControlRuns.push(this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: controlWorkDir }));
controlSnapshots.push(snapshotDiff.snapshot);
}
// diff snapshots and get treatment raw paths
snapshotDiff = yield this.diffSnapshots({
const snapshotDiff = yield this.diffSnapshots({
loadAllSnapshots: true,
workDir: options.treatmentWorkDir,
});
const treatmentLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.controlWorkDir });
const treatmentLeakPaths = this.filterLeakPaths(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, { workDir: options.treatmentWorkDir });
const treatmentSnapshot = snapshotDiff.snapshot;
Console_1.default.topLevel(`${controlLeakPaths.length} traces from control group`);
const controlPathCounts = JSON.stringify(leakPathsFromControlRuns.map(leakPaths => leakPaths.length));
Console_1.default.topLevel(`${controlPathCounts} traces from control group`);
Console_1.default.topLevel(`${treatmentLeakPaths.length} traces from treatment group`);
const result = TraceBucket_1.default.clusterControlTreatmentPaths(controlLeakPaths, controlSnapshot, treatmentLeakPaths, treatmentSnapshot, Utils_1.default.aggregateDominatorMetrics, {
const result = TraceBucket_1.default.clusterControlTreatmentPaths(leakPathsFromControlRuns, controlSnapshots, treatmentLeakPaths, treatmentSnapshot, Utils_1.default.aggregateDominatorMetrics, {
strategy: Config_1.default.isMLClustering

@@ -93,4 +99,5 @@ ? new MLTraceSimilarityStrategy_1.default()

yield this.serializeClusterUpdate(result.treatmentOnlyClusters);
// TODO (lgong): log leak traces
return [];
// serialize JSON file with detailed leak trace information
const treatmentOnlyPaths = result.treatmentOnlyClusters.map(c => c.path);
return LeakTraceDetailsLogger_1.default.logTraces(snapshotDiff.leakedHeapNodeIdSet, snapshotDiff.snapshot, snapshotDiff.listOfLeakedHeapNodeIdSet, treatmentOnlyPaths, Config_1.default.traceJsonOutDir);
});

@@ -132,3 +139,3 @@ }

}
this.dumpPathByNodeId(snapshotLeakedHeapNodeIdSet, snapshot, nodeIdsInSnapshots, Config_1.default.focusFiberNodeId, Config_1.default.viewJsonFile, Config_1.default.singleReportSummary);
this.dumpPathByNodeId(snapshotLeakedHeapNodeIdSet, snapshot, nodeIdsInSnapshots, Config_1.default.focusFiberNodeId, Config_1.default.viewJsonFile, Config_1.default.singleReportSummary, { printConsoleOnly: true });
});

@@ -357,2 +364,3 @@ }

this.filterLeakedObjects(leakedNodeIds, snapshot);
const leakTraceFilter = new LeakTraceFilter_1.LeakTraceFilter();
const nodeIdInPaths = new Set();

@@ -369,3 +377,4 @@ const paths = [];

const p = finder.getPathToGCRoots(snapshot, node);
if (!p || !Utils_1.default.isInterestingPath(p)) {
if (p == null ||
!leakTraceFilter.filter(p, { config: Config_1.default, leakedNodeIds, snapshot })) {
return;

@@ -462,6 +471,9 @@ }

LeakTraceDetailsLogger_1.default.logTrace(leakedIdSet, snapshot, nodeIdsInSnapshots, path, pathLoaderFile);
let pathSummary = Serializer_1.default.summarizePath(path, nodeIdInPaths, snapshot, { color: true });
Console_1.default.topLevel(pathSummary);
if (options.printConsoleOnly) {
return;
}
const tabsOrder = Utils_1.default.loadTabsOrder(FileManager_1.default.getSnapshotSequenceMetaFile(options));
const interactionSummary = Serializer_1.default.summarizeTabsOrder(tabsOrder);
let pathSummary = Serializer_1.default.summarizePath(path, nodeIdInPaths, snapshot, { color: true });
Console_1.default.topLevel(pathSummary);
pathSummary = Serializer_1.default.summarizePath(path, nodeIdInPaths, snapshot);

@@ -468,0 +480,0 @@ const summary = `Page Interaction: \n${interactionSummary}\n\n` +

@@ -10,5 +10,5 @@ /**

*/
import type { HaltOrThrowOptions, HeapNodeIdSet, ShellOptions } from './Types';
import type { HaltOrThrowOptions, HeapNodeIdSet, ShellOptions, StringRecord } from './Types';
import type { Browser, Page } from 'puppeteer';
import type { AnyAyncFunction, AnyOptions, E2EStepInfo, IHeapSnapshot, IHeapNode, IHeapEdge, IScenario, ILeakFilter, LeakTracePathItem, RunMetaInfo, RawHeapSnapshot, Nullable, Optional } from './Types';
import type { AnyAyncFunction, AnyOptions, E2EStepInfo, IHeapSnapshot, IHeapNode, IHeapEdge, IScenario, ILeakFilter, LeakTracePathItem, RawHeapSnapshot, Nullable, Optional } from './Types';
declare function isHermesInternalObject(node: IHeapNode): boolean;

@@ -18,2 +18,4 @@ declare function isStackTraceFrame(node: IHeapNode): boolean;

declare function isDetachedFiberNode(node: IHeapNode): boolean;
declare function isDOMInternalNode(node: Optional<IHeapNode>): boolean;
declare function isGlobalHandlesNode(node: Optional<IHeapNode>): boolean;
declare function isDetachedDOMNode(node: Optional<IHeapNode>, args?: AnyOptions): boolean;

@@ -28,2 +30,5 @@ declare function isWeakMapEdge(edge: IHeapEdge): boolean;

declare function isDOMNodeIncomplete(node: IHeapNode): boolean;
declare function isXMLDocumentNode(node: IHeapNode): boolean;
declare function isHTMLDocumentNode(node: IHeapNode): boolean;
declare function isDOMTextNode(node: IHeapNode): boolean;
declare function isRootNode(node: IHeapNode, opt?: AnyOptions): boolean;

@@ -70,8 +75,4 @@ declare function isDirectPropEdge(edge: IHeapEdge): boolean;

declare function hasOnlyWeakReferrers(node: IHeapNode): boolean;
declare function getRunMetaFilePath(): string;
declare function loadRunMetaInfo(metaFile?: Optional<string>): RunMetaInfo;
declare function loadTargetInfoFromRunMeta(): void;
declare function getSnapshotSequenceFilePath(): string;
declare function loadTabsOrder(metaFile?: Optional<string>): E2EStepInfo[];
declare function isInterestingPath(p: LeakTracePathItem): boolean;
declare function isObjectNode(node: IHeapNode): boolean;

@@ -136,2 +137,4 @@ declare function isPlainJSObjectNode(node: IHeapNode): boolean;

declare function getNumberAtPercentile(arr: number[], percentile: number): number;
declare function mapToObject(map: Map<string, string>): StringRecord;
declare function objectToMap(object: StringRecord): Map<string, string>;
declare const _default: {

@@ -142,5 +145,5 @@ aggregateDominatorMetrics: typeof aggregateDominatorMetrics;

camelCaseToReadableString: typeof camelCaseToReadableString;
checkIsChildOfParent: typeof checkIsChildOfParent;
checkSnapshots: typeof checkSnapshots;
checkUninstalledLibrary: typeof checkUninstalledLibrary;
checkIsChildOfParent: typeof checkIsChildOfParent;
closePuppeteer: typeof closePuppeteer;

@@ -154,9 +157,10 @@ dumpSnapshot: typeof dumpSnapshot;

getAllDominators: typeof getAllDominators;
getBooleanNodeValue: typeof getBooleanNodeValue;
getClosureSourceUrl: typeof getClosureSourceUrl;
getConditionalDominatorIds: typeof getConditionalDominatorIds;
getEdgeByNameAndType: typeof getEdgeByNameAndType;
getError: typeof getError;
getEdgeByNameAndType: typeof getEdgeByNameAndType;
getLastNodeId: typeof getLastNodeId;
getLeakTracePathLength: typeof getLeakTracePathLength;
getLeakedNode: typeof getLeakedNode;
getLeakTracePathLength: typeof getLeakTracePathLength;
getNodesIdSet: typeof getNodesIdSet;

@@ -169,13 +173,12 @@ getNumberAtPercentile: typeof getNumberAtPercentile;

getRetainedSize: typeof getRetainedSize;
getRunMetaFilePath: typeof getRunMetaFilePath;
getScenarioName: typeof getScenarioName;
getSingleSnapshotFileForAnalysis: typeof getSingleSnapshotFileForAnalysis;
getSnapshotDirForAnalysis: typeof getSnapshotDirForAnalysis;
getSnapshotFilePath: typeof getSnapshotFilePath;
getSnapshotFilePathWithTabType: typeof getSnapshotFilePathWithTabType;
getSnapshotFilesFromTabsOrder: typeof getSnapshotFilesFromTabsOrder;
getSnapshotFilesInDir: typeof getSnapshotFilesInDir;
getSnapshotFilesFromTabsOrder: typeof getSnapshotFilesFromTabsOrder;
getSnapshotFromFile: typeof getSnapshotFromFile;
getSnapshotNodeIdsFromFile: typeof getSnapshotNodeIdsFromFile;
getSnapshotSequenceFilePath: typeof getSnapshotSequenceFilePath;
getSnapshotFilePath: typeof getSnapshotFilePath;
getSnapshotFilePathWithTabType: typeof getSnapshotFilePathWithTabType;
getStringNodeValue: typeof getStringNodeValue;

@@ -191,14 +194,17 @@ getToNodeByEdge: typeof getToNodeByEdge;

isBlinkRootNode: typeof isBlinkRootNode;
isDOMInternalNode: typeof isDOMInternalNode;
isDOMNodeIncomplete: typeof isDOMNodeIncomplete;
isDOMTextNode: typeof isDOMTextNode;
isDebuggableNode: typeof isDebuggableNode;
isDetachedDOMNode: typeof isDetachedDOMNode;
isDetachedFiberNode: typeof isDetachedFiberNode;
isDetachedDOMNode: typeof isDetachedDOMNode;
isDirectPropEdge: typeof isDirectPropEdge;
isDocumentDOMTreesRoot: typeof isDocumentDOMTreesRoot;
isDOMNodeIncomplete: typeof isDOMNodeIncomplete;
isEssentialEdge: typeof isEssentialEdge;
isFiberNode: typeof isFiberNode;
isFiberNodeDeletionsEdge: typeof isFiberNodeDeletionsEdge;
isGlobalHandlesNode: typeof isGlobalHandlesNode;
isHTMLDocumentNode: typeof isHTMLDocumentNode;
isHermesInternalObject: typeof isHermesInternalObject;
isHostRoot: typeof isHostRoot;
isInterestingPath: typeof isInterestingPath;
isMeaningfulEdge: typeof isMeaningfulEdge;

@@ -222,9 +228,9 @@ isMeaningfulNode: typeof isMeaningfulNode;

isWeakMapEdgeToValue: typeof isWeakMapEdgeToValue;
isXMLDocumentNode: typeof isXMLDocumentNode;
iterateChildFiberNodes: typeof iterateChildFiberNodes;
iterateDescendantFiberNodes: typeof iterateDescendantFiberNodes;
loadRunMetaInfo: typeof loadRunMetaInfo;
loadLeakFilter: typeof loadLeakFilter;
loadScenario: typeof loadScenario;
loadTabsOrder: typeof loadTabsOrder;
loadTargetInfoFromRunMeta: typeof loadTargetInfoFromRunMeta;
mapToObject: typeof mapToObject;
markAllDetachedFiberNode: typeof markAllDetachedFiberNode;

@@ -234,2 +240,3 @@ markAlternateFiberNode: typeof markAlternateFiberNode;

normalizeBaseUrl: typeof normalizeBaseUrl;
objectToMap: typeof objectToMap;
pathHasDetachedHTMLNode: typeof pathHasDetachedHTMLNode;

@@ -247,5 +254,4 @@ pathHasEdgeWithIndex: typeof pathHasEdgeWithIndex;

upperCaseFirstCharacter: typeof upperCaseFirstCharacter;
getBooleanNodeValue: typeof getBooleanNodeValue;
};
export default _default;
//# sourceMappingURL=Utils.d.ts.map

@@ -56,3 +56,2 @@ "use strict";

const HeapParser_1 = __importDefault(require("./HeapParser"));
const BrowserInfo_1 = __importDefault(require("./BrowserInfo"));
const memCache = Object.create(null);

@@ -137,2 +136,17 @@ const FileManager_1 = __importDefault(require("./FileManager"));

}
// return true if this node is InternalNode (native)
function isDOMInternalNode(node) {
if (node == null) {
return false;
}
return (node.type === 'native' &&
(node.name === 'InternalNode' || node.name === 'Detached InternalNode'));
}
// return true the the nodee is a global handles node
function isGlobalHandlesNode(node) {
if (node == null) {
return false;
}
return node.name === '(Global handles)' && node.type === 'synthetic';
}
// this function returns a more general sense of DOM nodes. Specifically,

@@ -216,9 +230,28 @@ // any detached DOM nodes (e.g., HTMLXXElement, IntersectionObserver etc.)

}
return node.type === 'synthetic' && node.name === 'Pending activities';
if (node.type !== 'synthetic' && node.type !== 'native') {
return false;
}
return node.name === 'Pending activities';
}
const htmlElementRegex = /^HTML.*Element$/;
const svgElementRegex = /^SVG.*Element$/;
const htmlCollectionRegex = /^HTML.*Collection$/;
const cssElementRegex = /^CSS/;
const styleSheetRegex = /StyleSheet/;
// special DOM element names that are not
// included in the previous regex definitions
const domElementSpecialNames = new Set([
'DOMTokenList',
'HTMLDocument',
'InternalNode',
'Text',
'XMLDocument',
]);
// check the node against a curated list of known HTML Elements
// the list may be incomplete
function isDOMNodeIncomplete(node) {
if (node.type !== 'native') {
return false;
}
let name = node.name;
const pattern = /^HTML.*Element$/;
const detachedPrefix = 'Detached ';

@@ -228,4 +261,18 @@ if (name.startsWith(detachedPrefix)) {

}
return pattern.test(name);
return (htmlElementRegex.test(name) ||
svgElementRegex.test(name) ||
cssElementRegex.test(name) ||
styleSheetRegex.test(name) ||
htmlCollectionRegex.test(name) ||
domElementSpecialNames.has(name));
}
function isXMLDocumentNode(node) {
return node.type === 'native' && node.name === 'XMLDocument';
}
function isHTMLDocumentNode(node) {
return node.type === 'native' && node.name === 'HTMLDocument';
}
function isDOMTextNode(node) {
return node.type === 'native' && node.name === 'Text';
}
function isRootNode(node, opt = {}) {

@@ -478,3 +525,5 @@ if (!node) {

if (!node) {
Console_1.default.warning(`node @${id} is not found`);
if (Config_1.default.verbose) {
Console_1.default.warning(`node @${id} is not found`);
}
return;

@@ -839,23 +888,2 @@ }

}
function getRunMetaFilePath() {
return Config_1.default.useExternalSnapshot
? Config_1.default.externalRunMetaFile
: Config_1.default.runMetaFile;
}
function loadRunMetaInfo(metaFile = undefined) {
const file = metaFile || getRunMetaFilePath();
try {
const content = fs_1.default.readFileSync(file, 'UTF-8');
return JSON.parse(content);
}
catch (_) {
throw haltOrThrow('Run info missing. Please make sure `memlab run` is complete.');
}
}
function loadTargetInfoFromRunMeta() {
const meta = loadRunMetaInfo();
Config_1.default.targetApp = meta.app;
Config_1.default.targetTab = meta.interaction;
BrowserInfo_1.default.load(meta.browserInfo);
}
function getSnapshotSequenceFilePath() {

@@ -879,3 +907,5 @@ if (!Config_1.default.useExternalSnapshot) {

try {
const file = metaFile || getSnapshotSequenceFilePath();
const file = metaFile != null && fs_1.default.existsSync(metaFile)
? metaFile
: getSnapshotSequenceFilePath();
const content = fs_1.default.readFileSync(file, 'UTF-8');

@@ -888,27 +918,2 @@ return JSON.parse(content);

}
// if true the leak trace is will be reported
function isInterestingPath(p) {
// do not filter paths when analyzing Hermes snapshots
if (Config_1.default.jsEngine === 'hermes') {
return true;
}
// if the path has pattern: Window -> [InternalNode]+ -> DetachedElement
if (Config_1.default.hideBrowserLeak && internalNodeRetainsDetachedElement(p)) {
return false;
}
// if the path has pattern: ShadowRoot -> DetachedElement
if (Config_1.default.hideBrowserLeak && shadowRootRetainsDetachedElement(p)) {
return false;
}
// if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
if (Config_1.default.hideBrowserLeak && styleEngineRetainsDetachedElement(p)) {
return false;
}
// if the path has pattern: Pending activitiies -> DetachedElement
if (Config_1.default.hideBrowserLeak &&
pendingActivitiesRetainsDetachedElementChain(p)) {
return false;
}
return true;
}
// return true if the heap node represents JS object or closure

@@ -931,85 +936,2 @@ function isObjectNode(node) {

}
// check if the path has pattern:
// Window -> [InternalNode | Text]+ -> DetachedElement
function internalNodeRetainsDetachedElement(path) {
var _a, _b;
if (!path) {
return false;
}
let p = path;
// GC root is not Window
if (!p.node || !p.node.name.startsWith('Window')) {
return false;
}
p = p.next;
// Window is not poining to InternalNode
if (!p || !p.node || p.node.name !== 'InternalNode') {
return false;
}
// skip the rest InternalNode
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') {
p = p.next;
if (!p) {
return false;
}
}
// check if the node is a detached element
return p && isDetachedDOMNode(p.node);
}
// check if the path has pattern: ShadowRoot -> DetachedElement
function shadowRootRetainsDetachedElement(path) {
let p = path;
// find the ShadowRoot
while (p && p.node && p.node.name !== 'ShadowRoot') {
p = p.next;
if (!p) {
return false;
}
}
p = p.next;
// check if the node is a detached element
return !!p && isDetachedDOMNode(p.node);
}
// check if the path has pattern: StyleEngine -> InternalNode -> DetachedElement
function styleEngineRetainsDetachedElement(path) {
let p = path;
// find the StyleEngine
while (p && p.node && p.node.name !== 'StyleEngine') {
p = p.next;
if (!p) {
return false;
}
}
p = p.next;
// StyleEngine is not poining to InternalNode
if (!p || !p.node || p.node.name !== 'InternalNode') {
return false;
}
p = p.next;
// check if the InternalNode is pointing to a detached element
return !!p && isDetachedDOMNode(p.node);
}
function pendingActivitiesRetainsDetachedElementChain(path) {
let p = path;
// find the Pending activities
while (p && p.node && !isPendingActivityNode(p.node)) {
p = p.next;
if (!p) {
return false;
}
}
p = p.next;
if (!p || !p.node) {
return false;
}
// all the following reference chain is detached DOM elements
// pointing to other detached DOM elements
while (p && p.node) {
if (!isDetachedDOMNode(p.node)) {
return false;
}
p = p.next;
}
return true;
}
function pathHasDetachedHTMLNode(path) {

@@ -1794,2 +1716,5 @@ if (!path) {

}
if (options.throwError) {
throw ex;
}
if (options.ignoreError === true) {

@@ -1837,2 +1762,16 @@ return '';

}
function mapToObject(map) {
const ret = Object.create(null);
map.forEach((v, k) => {
ret[k] = v;
});
return ret;
}
function objectToMap(object) {
const ret = new Map();
for (const k of Object.keys(object)) {
ret.set(k, object[k]);
}
return ret;
}
exports.default = {

@@ -1843,5 +1782,5 @@ aggregateDominatorMetrics,

camelCaseToReadableString,
checkIsChildOfParent,
checkSnapshots,
checkUninstalledLibrary,
checkIsChildOfParent,
closePuppeteer,

@@ -1855,9 +1794,10 @@ dumpSnapshot,

getAllDominators,
getBooleanNodeValue,
getClosureSourceUrl,
getConditionalDominatorIds,
getEdgeByNameAndType,
getError,
getEdgeByNameAndType,
getLastNodeId,
getLeakTracePathLength,
getLeakedNode,
getLeakTracePathLength,
getNodesIdSet,

@@ -1870,13 +1810,12 @@ getNumberAtPercentile,

getRetainedSize,
getRunMetaFilePath,
getScenarioName,
getSingleSnapshotFileForAnalysis,
getSnapshotDirForAnalysis,
getSnapshotFilePath,
getSnapshotFilePathWithTabType,
getSnapshotFilesFromTabsOrder,
getSnapshotFilesInDir,
getSnapshotFilesFromTabsOrder,
getSnapshotFromFile,
getSnapshotNodeIdsFromFile,
getSnapshotSequenceFilePath,
getSnapshotFilePath,
getSnapshotFilePathWithTabType,
getStringNodeValue,

@@ -1892,14 +1831,17 @@ getToNodeByEdge,

isBlinkRootNode,
isDOMInternalNode,
isDOMNodeIncomplete,
isDOMTextNode,
isDebuggableNode,
isDetachedDOMNode,
isDetachedFiberNode,
isDetachedDOMNode,
isDirectPropEdge,
isDocumentDOMTreesRoot,
isDOMNodeIncomplete,
isEssentialEdge,
isFiberNode,
isFiberNodeDeletionsEdge,
isGlobalHandlesNode,
isHTMLDocumentNode,
isHermesInternalObject,
isHostRoot,
isInterestingPath,
isMeaningfulEdge,

@@ -1923,9 +1865,9 @@ isMeaningfulNode,

isWeakMapEdgeToValue,
isXMLDocumentNode,
iterateChildFiberNodes,
iterateDescendantFiberNodes,
loadRunMetaInfo,
loadLeakFilter,
loadScenario,
loadTabsOrder,
loadTargetInfoFromRunMeta,
mapToObject,
markAllDetachedFiberNode,

@@ -1935,2 +1877,3 @@ markAlternateFiberNode,

normalizeBaseUrl,
objectToMap,
pathHasDetachedHTMLNode,

@@ -1948,3 +1891,2 @@ pathHasEdgeWithIndex,

upperCaseFirstCharacter,
getBooleanNodeValue,
};

@@ -190,2 +190,3 @@ "use strict";

meta_data: JSON.stringify({
extraRunInfo: Utils_1.default.mapToObject(Config_1.default.extraRunInfoMap),
browser_info: BrowserInfo_1.default,

@@ -192,0 +193,0 @@ visit_plan: tabsOrder,

@@ -431,7 +431,21 @@ "use strict";

isLessPreferableEdge(edge) {
const fromNode = edge.fromNode;
const toNode = edge.toNode;
// pending activities -> DOM element is less preferrable
if (Utils_1.default.isPendingActivityNode(edge.fromNode) &&
Utils_1.default.isDOMNodeIncomplete(edge.toNode)) {
if (Utils_1.default.isPendingActivityNode(fromNode) &&
Utils_1.default.isDOMNodeIncomplete(toNode)) {
return true;
}
// detached DOM node -> non-detached DOM node is less preferable
if (Utils_1.default.isDetachedDOMNode(fromNode) &&
Utils_1.default.isDOMNodeIncomplete(toNode) &&
!Utils_1.default.isDetachedDOMNode(toNode)) {
return true;
}
// non-detached DOM node -> detached DOM node is less preferable
if (Utils_1.default.isDOMNodeIncomplete(fromNode) &&
!Utils_1.default.isDetachedDOMNode(fromNode) &&
Utils_1.default.isDetachedDOMNode(toNode)) {
return true;
}
return Config_1.default.edgeNameGreyList.has(String(edge.name_or_index));

@@ -438,0 +452,0 @@ }

@@ -63,2 +63,3 @@ "use strict";

}
Console_1.default.overwrite('');
return { staleClusters, clustersToAdd, allClusters: clusters };

@@ -65,0 +66,0 @@ }

@@ -40,3 +40,3 @@ /**

private static initEmptyCluster;
static clusterControlTreatmentPaths(controlPaths: LeakTracePathItem[], controlSnapshot: IHeapSnapshot, treatmentPaths: LeakTracePathItem[], treatmentSnapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb, option?: {
static clusterControlTreatmentPaths(leakPathsFromControlRuns: LeakTracePathItem[][], controlSnapshots: IHeapSnapshot[], treatmentPaths: LeakTracePathItem[], treatmentSnapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb, option?: {
strategy?: IClusterStrategy;

@@ -43,0 +43,0 @@ }): ControlTreatmentClusterResult;

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

}
static clusterControlTreatmentPaths(controlPaths, controlSnapshot, treatmentPaths, treatmentSnapshot, aggregateDominatorMetrics, option = {}) {
static clusterControlTreatmentPaths(leakPathsFromControlRuns, controlSnapshots, treatmentPaths, treatmentSnapshot, aggregateDominatorMetrics, option = {}) {
const result = {

@@ -319,3 +319,4 @@ controlOnlyClusters: [],

Console_1.default.overwrite('Clustering leak traces');
if (controlPaths.length === 0 && treatmentPaths.length === 0) {
const totalControlPaths = leakPathsFromControlRuns.reduce((count, leakPaths) => count + leakPaths.length, 0);
if (totalControlPaths === 0 && treatmentPaths.length === 0) {
Console_1.default.midLevel('No leaks found');

@@ -325,3 +326,4 @@ return result;

// sample paths if there are too many
controlPaths = this.samplePaths(controlPaths);
const flattenedLeakPathsFromControlRuns = leakPathsFromControlRuns.reduce((arr, leakPaths) => [...arr, ...leakPaths], []);
const controlPaths = this.samplePaths(flattenedLeakPathsFromControlRuns);
treatmentPaths = this.samplePaths(treatmentPaths);

@@ -336,2 +338,4 @@ // build control trace to control path map

const { allClusters } = NormalizedTrace.diffTraces([...controlTraces, ...treatmentTraces], [], option);
// pick one of the control heap snapshots
const controlSnapshot = controlSnapshots[0];
// construct TraceCluster from clustering result

@@ -338,0 +342,0 @@ allClusters.forEach((traces) => {

{
"name": "@memlab/core",
"version": "1.1.20",
"version": "1.1.21",
"license": "MIT",

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

Sorry, the diff of this file is too big to display

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