@memlab/core
Advanced tools
Comparing version 1.1.19 to 1.1.20
@@ -31,3 +31,3 @@ "use strict"; | ||
test('String heap object APIs work', () => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a, _b, _c; | ||
var _a, _b, _c, _d, _e, _f; | ||
class TestObject { | ||
@@ -48,2 +48,4 @@ constructor() { | ||
expect(testObject).not.toBe(null); | ||
// test the number of referrers getter | ||
expect(testObject === null || testObject === void 0 ? void 0 : testObject.numOfReferrers).toBeGreaterThan(0); | ||
// testObject.originalString === 'test' | ||
@@ -63,2 +65,11 @@ const originalString = testObject === null || testObject === void 0 ? void 0 : testObject.getReferenceNode('originalString'); | ||
expect((_c = complexConcatString === null || complexConcatString === void 0 ? void 0 : complexConcatString.toStringNode()) === null || _c === void 0 ? void 0 : _c.stringValue).toBe('prefix_value_123_suffix'); | ||
// test the toJSONString API | ||
let strRepresentation = (_d = concatString === null || concatString === void 0 ? void 0 : concatString.toJSONString()) !== null && _d !== void 0 ? _d : '{}'; | ||
let rep = JSON.parse(strRepresentation); | ||
expect(rep.type).toBe('concatenated string'); | ||
expect(rep.stringValue).toBe(undefined); | ||
strRepresentation = (_f = (_e = concatString === null || concatString === void 0 ? void 0 : concatString.toStringNode()) === null || _e === void 0 ? void 0 : _e.toJSONString()) !== null && _f !== void 0 ? _f : '{}'; | ||
rep = JSON.parse(strRepresentation); | ||
expect(rep.type).toBe('concatenated string'); | ||
expect(rep.stringValue).toBe('prefix_suffix'); | ||
}), timeout); |
@@ -33,2 +33,8 @@ /** | ||
} | ||
if (plotData.length === 0) { | ||
if (Config_1.default.verbose) { | ||
Console_1.default.warning('no memory usage data to plot'); | ||
} | ||
return; | ||
} | ||
// normalize plot data | ||
@@ -35,0 +41,0 @@ const minY = 1; |
@@ -199,2 +199,4 @@ /** | ||
interceptScript: boolean; | ||
isAnalyzingMainThread: boolean; | ||
targetWorkerTitle: Nullable<string>; | ||
constructor(options?: ConfigOption); | ||
@@ -201,0 +203,0 @@ private initInternalConfigs; |
@@ -214,2 +214,6 @@ "use strict"; | ||
this.warmupRepeat = 2; | ||
// by default, analyzing heap in main thread | ||
this.isAnalyzingMainThread = true; | ||
// target worker's title | ||
this.targetWorkerTitle = null; | ||
// default waiting time when there is no page load checker callback | ||
@@ -216,0 +220,0 @@ this.delayWhenNoPageLoadCheck = 2000; |
@@ -54,3 +54,5 @@ /** | ||
getRunMetaFile(options?: FileOption): string; | ||
getRunMetaExternalTemplateFile(): string; | ||
getSnapshotSequenceMetaFile(options?: FileOption): string; | ||
getSnapshotSequenceExternalTemplateFile(): string; | ||
getInputDataDir(): string; | ||
@@ -76,2 +78,3 @@ getAllFilesInSubDirs(dir: string): string[]; | ||
isWithinInternalDirectory(filePath: string): boolean; | ||
createDefaultVisitOrderMetaFile(options?: FileOption): void; | ||
initDirs(config: MemLabConfig, options?: FileOption): void; | ||
@@ -78,0 +81,0 @@ } |
@@ -182,5 +182,11 @@ "use strict"; | ||
} | ||
getRunMetaExternalTemplateFile() { | ||
return path_1.default.join(this.getCodeDataDir(), 'run-meta.json'); | ||
} | ||
getSnapshotSequenceMetaFile(options = FileManager.defaultFileOption) { | ||
return path_1.default.join(this.getCurDataDir(options), 'snap-seq.json'); | ||
} | ||
getSnapshotSequenceExternalTemplateFile() { | ||
return path_1.default.join(this.getCodeDataDir(), 'visit-order.json'); | ||
} | ||
getInputDataDir() { | ||
@@ -335,2 +341,33 @@ return path_1.default.join(this.getDefaultWorkDir(), 'input'); | ||
} | ||
createDefaultVisitOrderMetaFile(options = FileManager.defaultFileOption) { | ||
// if memlab/data/cur doesn't exist, return | ||
const curDataDir = this.getCurDataDir(options); | ||
if (!fs_extra_1.default.existsSync(curDataDir)) { | ||
return; | ||
} | ||
// if the snap-seq.json file exists, return | ||
const snapshotSeqMetaFile = this.getSnapshotSequenceMetaFile(options); | ||
if (fs_extra_1.default.existsSync(snapshotSeqMetaFile)) { | ||
return; | ||
} | ||
// if there is no .heapsnapshot file, return | ||
const files = fs_extra_1.default.readdirSync(curDataDir); | ||
const snapshotFile = files.find(file => file.endsWith('.heapsnapshot')); | ||
if (snapshotFile == null) { | ||
return; | ||
} | ||
// If there is at least one snapshot, create a snap-seq.json file. | ||
// First, get the meta file for leak detection in a single heap snapshot | ||
const codeDataDir = this.getCodeDataDir(); | ||
const singleSnapshotMetaFile = path_1.default.join(codeDataDir, 'visit-order-single-snapshot.json'); | ||
const visitOrder = JSON.parse(fs_extra_1.default.readFileSync(singleSnapshotMetaFile, 'UTF-8')); | ||
// fill in snapshot file name for each entry with snapshot: true | ||
visitOrder.forEach(step => { | ||
if (step.snapshot === true) { | ||
step.snapshotFile = snapshotFile; | ||
} | ||
}); | ||
// save the snapshot meta file | ||
fs_extra_1.default.writeFileSync(snapshotSeqMetaFile, JSON.stringify(visitOrder, null, 2), 'UTF-8'); | ||
} | ||
initDirs(config, options = FileManager.defaultFileOption) { | ||
@@ -344,2 +381,7 @@ // cache the last processed memlab config instance | ||
const workDir = this.getWorkDir(options); | ||
// if errorWhenAbsent is set to true, make it | ||
// an error when the working directory does not exist | ||
if (options.errorWhenAbsent && !fs_extra_1.default.existsSync(workDir)) { | ||
throw Utils_1.default.haltOrThrow(`work dir does not exist: ${workDir}`); | ||
} | ||
// remember the current working directory | ||
@@ -382,5 +424,5 @@ // especially if this is a transcient working directory | ||
config.reportScreenshotFile = path_1.default.join(outDir, 'report.png'); | ||
const codeDataDir = this.getCodeDataDir(); | ||
config.externalRunMetaFile = path_1.default.join(codeDataDir, 'run-meta.json'); | ||
config.externalSnapshotVisitOrderFile = path_1.default.join(codeDataDir, 'visit-order.json'); | ||
config.externalRunMetaFile = this.getRunMetaExternalTemplateFile(); | ||
config.externalSnapshotVisitOrderFile = | ||
this.getSnapshotSequenceExternalTemplateFile(); | ||
joinAndProcessDir(options, this.getUniqueTraceClusterDir(options)); | ||
@@ -392,2 +434,3 @@ config.newUniqueClusterDir = joinAndProcessDir(options, this.getNewUniqueTraceClusterDir(options)); | ||
config.allClusterSummaryFile = this.getAllClusterSummaryFile(options); | ||
this.createDefaultVisitOrderMetaFile(options); | ||
} | ||
@@ -394,0 +437,0 @@ } |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
import type { IHeapEdge } from '../Types'; | ||
import type { AnyRecord, AnyValue, IHeapEdge } from '../Types'; | ||
import type HeapSnapshot from './HeapSnapshot'; | ||
@@ -27,3 +27,5 @@ import HeapNode from './HeapNode'; | ||
get fromNode(): HeapNode; | ||
getJSONifyableObject(): AnyRecord; | ||
toJSONString(...args: Array<AnyValue>): string; | ||
} | ||
//# sourceMappingURL=HeapEdge.d.ts.map |
@@ -74,3 +74,16 @@ /** | ||
} | ||
getJSONifyableObject() { | ||
return { | ||
name_or_index: this.name_or_index, | ||
type: this.type, | ||
edgeIndex: this.edgeIndex, | ||
toNode: this.toNode.getJSONifyableObject(), | ||
fromNode: this.fromNode.getJSONifyableObject(), | ||
}; | ||
} | ||
toJSONString(...args) { | ||
const rep = this.getJSONifyableObject(); | ||
return JSON.stringify(rep, ...args); | ||
} | ||
} | ||
exports.default = HeapEdge; |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
import type { IHeapLocation, IHeapNode, Nullable } from '../Types'; | ||
import type { AnyRecord, AnyValue, IHeapLocation, IHeapNode, Nullable } from '../Types'; | ||
import type HeapSnapshot from './HeapSnapshot'; | ||
@@ -23,3 +23,5 @@ export default class HeapLocation implements IHeapLocation { | ||
get column(): number; | ||
getJSONifyableObject(): AnyRecord; | ||
toJSONString(...args: Array<AnyValue>): string; | ||
} | ||
//# sourceMappingURL=HeapLocation.d.ts.map |
@@ -46,3 +46,17 @@ /** | ||
} | ||
getJSONifyableObject() { | ||
const node = this.node; | ||
const jsonNode = node == null ? null : node.getJSONifyableObject(); | ||
return { | ||
node: jsonNode, | ||
script_id: this.script_id, | ||
line: this.line, | ||
column: this.column, | ||
}; | ||
} | ||
toJSONString(...args) { | ||
const rep = this.getJSONifyableObject(); | ||
return JSON.stringify(rep, ...args); | ||
} | ||
} | ||
exports.default = HeapLocation; |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
import type { IHeapNode, IHeapEdge, Nullable, EdgeIterationCallback, Predicator, IHeapStringNode } from '../Types'; | ||
import type { IHeapNode, IHeapEdge, Nullable, EdgeIterationCallback, Predicator, IHeapStringNode, AnyRecord, AnyValue } from '../Types'; | ||
import type HeapSnapshot from './HeapSnapshot'; | ||
@@ -37,4 +37,7 @@ import HeapEdge from './HeapEdge'; | ||
findAnyReferrer(predicate: Predicator<IHeapEdge>): Nullable<IHeapEdge>; | ||
findAnyReferrerNode(predicate: Predicator<IHeapNode>): Nullable<IHeapNode>; | ||
findReferrers(predicate: Predicator<IHeapEdge>): IHeapEdge[]; | ||
findReferrerNodes(predicate: Predicator<IHeapNode>): IHeapNode[]; | ||
get referrers(): HeapEdge[]; | ||
get numOfReferrers(): number; | ||
forEachReferrer(callback: EdgeIterationCallback): void; | ||
@@ -58,3 +61,5 @@ get hasPathEdge(): boolean; | ||
toStringNode(): Nullable<IHeapStringNode>; | ||
getJSONifyableObject(): AnyRecord; | ||
toJSONString(...args: Array<AnyValue>): string; | ||
} | ||
//# sourceMappingURL=HeapNode.d.ts.map |
@@ -154,2 +154,13 @@ /** | ||
} | ||
findAnyReferrerNode(predicate) { | ||
let found = null; | ||
this.forEachReferrer((edge) => { | ||
const node = edge.fromNode; | ||
if (predicate(node)) { | ||
found = node; | ||
return { stop: true }; | ||
} | ||
}); | ||
return found; | ||
} | ||
findReferrers(predicate) { | ||
@@ -165,2 +176,13 @@ const ret = []; | ||
} | ||
findReferrerNodes(predicate) { | ||
const ret = []; | ||
this.forEachReferrer((edge) => { | ||
const node = edge.fromNode; | ||
if (predicate(node)) { | ||
ret.push(node); | ||
} | ||
return null; | ||
}); | ||
return ret; | ||
} | ||
get referrers() { | ||
@@ -179,2 +201,9 @@ const heapSnapshot = this.heapSnapshot; | ||
} | ||
get numOfReferrers() { | ||
const heapSnapshot = this.heapSnapshot; | ||
const firstRetainerIndex = heapSnapshot._firstRetainerIndex; | ||
const beginIdx = firstRetainerIndex[this.idx]; | ||
const endIdx = firstRetainerIndex[this.idx + 1]; | ||
return endIdx - beginIdx; | ||
} | ||
forEachReferrer(callback) { | ||
@@ -348,2 +377,19 @@ const heapSnapshot = this.heapSnapshot; | ||
} | ||
getJSONifyableObject() { | ||
return { | ||
id: this.id, | ||
name: this.name, | ||
type: this.type, | ||
self_size: this.self_size, | ||
trace_node_id: this.trace_node_id, | ||
nodeIndex: this.nodeIndex, | ||
outGoingEdgeCount: this.edge_count, | ||
incomingEdgeCount: this.numOfReferrers, | ||
contructorName: this.constructor.name, | ||
}; | ||
} | ||
toJSONString(...args) { | ||
const rep = this.getJSONifyableObject(); | ||
return JSON.stringify(rep, ...args); | ||
} | ||
} | ||
@@ -350,0 +396,0 @@ exports.default = HeapNode; |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
import type { IHeapNode, IHeapNodes, IHeapEdges, IHeapSnapshot, HeapNodeTypes, HeapEdgeTypes, HeapSnapshotMeta, RawHeapSnapshot, NumericDictionary, Nullable } from '../Types'; | ||
import type { AnyRecord, AnyValue, IHeapNode, IHeapNodes, IHeapEdges, IHeapSnapshot, HeapNodeTypes, HeapEdgeTypes, HeapSnapshotMeta, RawHeapSnapshot, NumericDictionary, Nullable } from '../Types'; | ||
import HeapNode from './HeapNode'; | ||
@@ -71,2 +71,4 @@ export default class HeapSnapshot implements IHeapSnapshot { | ||
constructor(snapshot: RawHeapSnapshot, _options?: Record<string, never>); | ||
getJSONifyableObject(): AnyRecord; | ||
toJSONString(...args: Array<AnyValue>): string; | ||
hasObjectWithClassName(className: string): boolean; | ||
@@ -73,0 +75,0 @@ getAnyObjectWithClassName(className: string): Nullable<IHeapNode>; |
@@ -132,2 +132,9 @@ /** | ||
} | ||
getJSONifyableObject() { | ||
return Object.assign({}, this.snapshot.snapshot); | ||
} | ||
toJSONString(...args) { | ||
const rep = this.getJSONifyableObject(); | ||
return JSON.stringify(rep, ...args); | ||
} | ||
hasObjectWithClassName(className) { | ||
@@ -134,0 +141,0 @@ let detected = false; |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
import type { IHeapStringNode } from '../Types'; | ||
import type { AnyRecord, IHeapStringNode } from '../Types'; | ||
import type HeapSnapshot from './HeapSnapshot'; | ||
@@ -18,3 +18,4 @@ import HeapNode from './HeapNode'; | ||
get stringValue(): string; | ||
getJSONifyableObject(): AnyRecord; | ||
} | ||
//# sourceMappingURL=HeapStringNode.d.ts.map |
@@ -44,3 +44,8 @@ /** | ||
} | ||
getJSONifyableObject() { | ||
const rep = super.getJSONifyableObject(); | ||
rep.stringValue = this.stringValue; | ||
return rep; | ||
} | ||
} | ||
exports.default = HeapStringNode; |
@@ -128,4 +128,6 @@ /** | ||
export declare function runShell(command: string, options?: ShellOptions): Nullable<string>; | ||
export declare function getRetainedSize(node: IHeapNode): number; | ||
export declare function aggregateDominatorMetrics(ids: HeapNodeIdSet, snapshot: IHeapSnapshot, checkNodeCb: (node: IHeapNode) => boolean, nodeMetricsCb: (node: IHeapNode) => number): number; | ||
declare function getRetainedSize(node: IHeapNode): number; | ||
declare function aggregateDominatorMetrics(ids: HeapNodeIdSet, snapshot: IHeapSnapshot, checkNodeCb: (node: IHeapNode) => boolean, nodeMetricsCb: (node: IHeapNode) => number): number; | ||
declare function getLeakTracePathLength(path: LeakTracePathItem): number; | ||
declare function getNumberAtPercentile(arr: number[], percentile: number): number; | ||
declare const _default: { | ||
@@ -153,3 +155,5 @@ aggregateDominatorMetrics: typeof aggregateDominatorMetrics; | ||
getLeakedNode: typeof getLeakedNode; | ||
getLeakTracePathLength: typeof getLeakTracePathLength; | ||
getNodesIdSet: typeof getNodesIdSet; | ||
getNumberAtPercentile: typeof getNumberAtPercentile; | ||
getNumberNodeValue: typeof getNumberNodeValue; | ||
@@ -156,0 +160,0 @@ getReadableBytes: typeof getReadableBytes; |
@@ -47,3 +47,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.aggregateDominatorMetrics = exports.getRetainedSize = exports.runShell = exports.resolveSnapshotFilePath = void 0; | ||
exports.runShell = exports.resolveSnapshotFilePath = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
@@ -1276,3 +1276,3 @@ const path_1 = __importDefault(require("path")); | ||
else { | ||
snapshotDir = FileManager_1.default.getCurDataDir({}); | ||
snapshotDir = FileManager_1.default.getCurDataDir({ workDir: Config_1.default.workDir }); | ||
} | ||
@@ -1352,2 +1352,5 @@ if (options.snapshotDir) { | ||
function getSnapshotFilePath(tab, options = {}) { | ||
if (tab.snapshotFile) { | ||
return path_1.default.join(FileManager_1.default.getCurDataDir(options), tab.snapshotFile); | ||
} | ||
const fileName = `s${tab.idx}.heapsnapshot`; | ||
@@ -1796,3 +1799,2 @@ if (options.workDir) { | ||
} | ||
exports.getRetainedSize = getRetainedSize; | ||
function aggregateDominatorMetrics(ids, snapshot, checkNodeCb, nodeMetricsCb) { | ||
@@ -1806,3 +1808,25 @@ let ret = 0; | ||
} | ||
exports.aggregateDominatorMetrics = aggregateDominatorMetrics; | ||
function getLeakTracePathLength(path) { | ||
let len = 0; | ||
let p = path; | ||
while (p) { | ||
p = p.next; | ||
++len; | ||
} | ||
return len; | ||
} | ||
function getNumberAtPercentile(arr, percentile) { | ||
arr.sort(function (a, b) { | ||
return a - b; | ||
}); | ||
const index = (percentile / 100) * arr.length; | ||
const indexInt = Math.floor(index); | ||
if (indexInt === index) { | ||
return arr[Math.floor(index)]; | ||
} | ||
if (indexInt + 1 < arr.length) { | ||
return (arr[indexInt] + arr[indexInt + 1]) / 2; | ||
} | ||
return arr[indexInt]; | ||
} | ||
exports.default = { | ||
@@ -1830,3 +1854,5 @@ aggregateDominatorMetrics, | ||
getLeakedNode, | ||
getLeakTracePathLength, | ||
getNodesIdSet, | ||
getNumberAtPercentile, | ||
getNumberNodeValue, | ||
@@ -1833,0 +1859,0 @@ getReadableBytes, |
@@ -15,2 +15,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Config_1 = __importDefault(require("../../lib/Config")); | ||
const Console_1 = __importDefault(require("../../lib/Console")); | ||
const ClusterUtils_1 = __importDefault(require("../ClusterUtils")); | ||
@@ -45,2 +47,9 @@ // cluster by putting similar traces together | ||
const traceToCheck = newTraces[i]; | ||
// use an odd number as the divider. If we choose 10 as the divider, | ||
// when updating the progress indicator, the final digit always ends | ||
// with a zero, which can appear strange and not representative of | ||
// the actual progress. | ||
if (!Config_1.default.isContinuousTest && i % 17 === 0) { | ||
Console_1.default.overwrite(`clustering trace: ${i} / ${newTraces.length}`); | ||
} | ||
for (let j = 0; j < clusters.length; ++j) { | ||
@@ -47,0 +56,0 @@ const repTrace = clusters[j][0]; |
@@ -27,2 +27,3 @@ /** | ||
static calculateClusterRetainedSize(cluster: TraceCluster, snapshot: IHeapSnapshot, aggregateDominatorMetrics: AggregateNodeCb): number; | ||
static getSamplePathMaxLength(paths: LeakTracePathItem[]): number; | ||
static samplePaths(paths: LeakTracePathItem[]): LeakTracePathItem[]; | ||
@@ -29,0 +30,0 @@ private static diffTraces; |
@@ -125,4 +125,11 @@ "use strict"; | ||
} | ||
static getSamplePathMaxLength(paths) { | ||
const lengthArr = paths.map(p => Utils_1.default.getLeakTracePathLength(p)); | ||
return Math.max(30, Utils_1.default.getNumberAtPercentile(lengthArr, 80)); | ||
} | ||
static samplePaths(paths) { | ||
const maxCount = 5000; | ||
if (paths.length <= maxCount) { | ||
return [...paths]; | ||
} | ||
const sampleRatio = Math.min(1, maxCount / paths.length); | ||
@@ -132,6 +139,13 @@ if (sampleRatio < 1) { | ||
Console_1.default.lowLevel(` Number of Traces: ${paths.length}`); | ||
Console_1.default.lowLevel(` Sampling Ratio: ${Utils_1.default.getReadablePercent(sampleRatio)}`); | ||
Console_1.default.lowLevel(` Sampling Ratio: ${Utils_1.default.getReadablePercent(sampleRatio)}`); | ||
} | ||
const ret = []; | ||
const samplePathMaxLength = NormalizedTrace.getSamplePathMaxLength(paths); | ||
if (Config_1.default.verbose) { | ||
Console_1.default.lowLevel(` Sample Trace's Max Length: ${samplePathMaxLength}`); | ||
} | ||
for (const p of paths) { | ||
if (Utils_1.default.getLeakTracePathLength(p) > samplePathMaxLength) { | ||
continue; | ||
} | ||
if (Math.random() < sampleRatio) { | ||
@@ -138,0 +152,0 @@ ret.push(p); |
@@ -10,3 +10,3 @@ /** | ||
*/ | ||
import type { EdgeIterationCallback, IHeapEdge, IHeapLocation, IHeapNode, IHeapSnapshot, IHeapStringNode, Nullable } from '../lib/Types'; | ||
import type { AnyValue, EdgeIterationCallback, IHeapEdge, IHeapLocation, IHeapNode, IHeapSnapshot, IHeapStringNode, Nullable } from '../lib/Types'; | ||
export declare class NodeRecord implements IHeapNode { | ||
@@ -36,2 +36,3 @@ kind: string; | ||
get referrers(): IHeapEdge[]; | ||
get numOfReferrers(): number; | ||
toStringNode(): IHeapStringNode; | ||
@@ -41,3 +42,5 @@ forEachReferrer(_callback: EdgeIterationCallback): void; | ||
findAnyReferrer(): Nullable<IHeapEdge>; | ||
findAnyReferrerNode(): Nullable<IHeapNode>; | ||
findReferrers(): IHeapEdge[]; | ||
findReferrerNodes(): IHeapNode[]; | ||
set hasPathEdge(f: boolean); | ||
@@ -57,2 +60,3 @@ get hasPathEdge(): boolean; | ||
getReferrerNodes(_edgeName: string | number, _edgeType?: string): IHeapNode[]; | ||
toJSONString(...args: Array<AnyValue>): string; | ||
constructor(node: IHeapNode); | ||
@@ -69,2 +73,3 @@ private extraceNodeName; | ||
constructor(edge: IHeapEdge); | ||
toJSONString(...args: Array<AnyValue>): string; | ||
set snapshot(s: IHeapSnapshot); | ||
@@ -71,0 +76,0 @@ get snapshot(): IHeapSnapshot; |
@@ -65,2 +65,5 @@ "use strict"; | ||
} | ||
get numOfReferrers() { | ||
throw new Error('NodeRecord.numOfReferrers cannot be read'); | ||
} | ||
toStringNode() { | ||
@@ -80,5 +83,11 @@ throw new Error('NodeRecord.toStringNode is not implemented'); | ||
} | ||
findAnyReferrerNode() { | ||
throw new Error('NodeRecord.findAnyReferrerNode is not implemented'); | ||
} | ||
findReferrers() { | ||
throw new Error('NodeRecord.findReferrers is not implemented'); | ||
} | ||
findReferrerNodes() { | ||
throw new Error('NodeRecord.findReferrerNodes is not implemented'); | ||
} | ||
set hasPathEdge(f) { | ||
@@ -150,2 +159,16 @@ throw new Error('NodeRecord.hasPathEdge cannot be assigned'); | ||
} | ||
toJSONString(...args) { | ||
const rep = { | ||
id: this.id, | ||
kind: this.kind, | ||
name: this.name, | ||
type: this.type, | ||
self_size: this.self_size, | ||
trace_node_id: this.trace_node_id, | ||
nodeIndex: this.nodeIndex, | ||
incomingEdgeCount: this.numOfReferrers, | ||
contructorName: this.constructor.name, | ||
}; | ||
return JSON.stringify(rep, ...args); | ||
} | ||
extraceNodeName(node) { | ||
@@ -169,2 +192,12 @@ // deserialized node may not have snapshot info | ||
} | ||
toJSONString(...args) { | ||
const rep = { | ||
kind: this.kind, | ||
name_or_index: this.name_or_index, | ||
type: this.type, | ||
edgeIndex: this.edgeIndex, | ||
to_node: this.to_node, | ||
}; | ||
return JSON.stringify(rep, ...args); | ||
} | ||
set snapshot(s) { | ||
@@ -171,0 +204,0 @@ throw new Error('EdgeRecord.snapshot cannot be assigned.'); |
{ | ||
"name": "@memlab/core", | ||
"version": "1.1.19", | ||
"version": "1.1.20", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "description": "memlab core libraries", |
Sorry, the diff of this file is too big to display
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
579579
130
14910