@memlab/api 1.0.3 → 1.0.6
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/README.md +3 -2
- package/dist/API.d.ts +36 -6
- package/dist/API.js +18 -11
- package/dist/__tests__/API/E2EFindLeaks.example.js +1 -1
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.js +16 -5
- package/dist/__tests__/heap/examples/example-1.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-1.js +37 -0
- package/dist/__tests__/heap/examples/example-2.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-2.js +33 -0
- package/dist/__tests__/heap/examples/example-3.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-3.js +33 -0
- package/dist/__tests__/heap/examples/example-4.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-4.js +32 -0
- package/dist/__tests__/heap/examples/example-5.test.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-5.test.js +41 -0
- package/dist/__tests__/heap/examples/example-6.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-6.js +32 -0
- package/dist/__tests__/heap/examples/example-7.test.d.ts +11 -0
- package/dist/__tests__/heap/examples/example-7.test.js +36 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +24 -6
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
This is the memlab API library. Add this dependency to your project
|
|
4
4
|
if you want to integrate memlab with your continuous testing system.
|
|
5
5
|
|
|
6
|
-
##
|
|
7
|
-
https://facebookincubator.github.io/memlab
|
|
6
|
+
## Online Resources
|
|
7
|
+
* [Official Website and Demo](https://facebookincubator.github.io/memlab)
|
|
8
|
+
* [Documentation](https://facebookincubator.github.io/memlab/docs/intro)
|
package/dist/API.d.ts
CHANGED
|
@@ -17,11 +17,17 @@ import BrowserInteractionResultReader from './result-reader/BrowserInteractionRe
|
|
|
17
17
|
* Options for configuring browser interaction run, all fields are optional
|
|
18
18
|
*/
|
|
19
19
|
export declare type RunOptions = {
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* test scenario specifying how to interact with browser
|
|
22
|
+
* (for more details view {@link IScenario})
|
|
23
|
+
*/
|
|
21
24
|
scenario?: IScenario;
|
|
22
25
|
/** the absolute path of cookies file */
|
|
23
26
|
cookiesFile?: string;
|
|
24
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* function to be evaluated in browser context after
|
|
29
|
+
* the web page initial load
|
|
30
|
+
*/
|
|
25
31
|
evalInBrowserAfterInitLoad?: AnyFunction;
|
|
26
32
|
/**
|
|
27
33
|
* if true, take heap snapshot for each interaction step,
|
|
@@ -29,6 +35,29 @@ export declare type RunOptions = {
|
|
|
29
35
|
* which steps it will take heap snapshots
|
|
30
36
|
*/
|
|
31
37
|
snapshotForEachStep?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* specify the working directory where you want memlab to dump
|
|
40
|
+
* heap snapshots and other meta data of the test run. If no
|
|
41
|
+
* working directory is provided, memlab will generate a random
|
|
42
|
+
* temp directory under the operating system's default directory
|
|
43
|
+
* for temporary files.
|
|
44
|
+
* Note: It's the caller's responsibility to make sure the
|
|
45
|
+
* specified working directory exists.
|
|
46
|
+
*/
|
|
47
|
+
workDir?: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* A data structure holding the result of the {@link run} API call.
|
|
51
|
+
*/
|
|
52
|
+
export declare type RunResult = {
|
|
53
|
+
/**
|
|
54
|
+
* leak traces detected and clustered from the browser interaction
|
|
55
|
+
*/
|
|
56
|
+
leaks: ISerializedInfo[];
|
|
57
|
+
/**
|
|
58
|
+
* a utility for reading browser interaction results from disk
|
|
59
|
+
*/
|
|
60
|
+
runResult: BrowserInteractionResultReader;
|
|
32
61
|
};
|
|
33
62
|
/**
|
|
34
63
|
* Options for memlab inter-package API calls
|
|
@@ -67,7 +96,8 @@ export declare function warmupAndTakeSnapshots(options?: RunOptions): Promise<Br
|
|
|
67
96
|
* and {@link findLeaks}.
|
|
68
97
|
*
|
|
69
98
|
* @param runOptions configure browser interaction run
|
|
70
|
-
* @returns
|
|
99
|
+
* @returns memory leaks detected and a utility reading browser
|
|
100
|
+
* interaction results from disk
|
|
71
101
|
* * **Examples**:
|
|
72
102
|
* ```javascript
|
|
73
103
|
* const {run} = require('@memlab/api');
|
|
@@ -76,17 +106,17 @@ export declare function warmupAndTakeSnapshots(options?: RunOptions): Promise<Br
|
|
|
76
106
|
* const scenario = {
|
|
77
107
|
* url: () => 'https://www.facebook.com',
|
|
78
108
|
* };
|
|
79
|
-
* const leaks = await run({scenario});
|
|
109
|
+
* const {leaks} = await run({scenario});
|
|
80
110
|
* })();
|
|
81
111
|
* ```
|
|
82
112
|
*/
|
|
83
|
-
export declare function run(runOptions?: RunOptions): Promise<
|
|
113
|
+
export declare function run(runOptions?: RunOptions): Promise<RunResult>;
|
|
84
114
|
/**
|
|
85
115
|
* This API runs E2E interaction and takes heap snapshots.
|
|
86
116
|
* This is equivalent to run `memlab snapshot` in CLI.
|
|
87
117
|
*
|
|
88
118
|
* @param options configure browser interaction run
|
|
89
|
-
* @returns browser interaction results
|
|
119
|
+
* @returns a utility reading browser interaction results from disk
|
|
90
120
|
* * **Examples**:
|
|
91
121
|
* ```javascript
|
|
92
122
|
* const {takeSnapshots} = require('@memlab/api');
|
package/dist/API.js
CHANGED
|
@@ -47,8 +47,7 @@ const BrowserInteractionResultReader_1 = __importDefault(require("./result-reade
|
|
|
47
47
|
*/
|
|
48
48
|
function warmupAndTakeSnapshots(options = {}) {
|
|
49
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
const config =
|
|
51
|
-
setConfigByRunOptions(config, options);
|
|
50
|
+
const config = getConfigFromRunOptions(options);
|
|
52
51
|
config.externalCookiesFile = options.cookiesFile;
|
|
53
52
|
config.scenario = options.scenario;
|
|
54
53
|
const testPlanner = new e2e_1.TestPlanner({ config });
|
|
@@ -66,7 +65,8 @@ exports.warmupAndTakeSnapshots = warmupAndTakeSnapshots;
|
|
|
66
65
|
* and {@link findLeaks}.
|
|
67
66
|
*
|
|
68
67
|
* @param runOptions configure browser interaction run
|
|
69
|
-
* @returns
|
|
68
|
+
* @returns memory leaks detected and a utility reading browser
|
|
69
|
+
* interaction results from disk
|
|
70
70
|
* * **Examples**:
|
|
71
71
|
* ```javascript
|
|
72
72
|
* const {run} = require('@memlab/api');
|
|
@@ -75,14 +75,13 @@ exports.warmupAndTakeSnapshots = warmupAndTakeSnapshots;
|
|
|
75
75
|
* const scenario = {
|
|
76
76
|
* url: () => 'https://www.facebook.com',
|
|
77
77
|
* };
|
|
78
|
-
* const leaks = await run({scenario});
|
|
78
|
+
* const {leaks} = await run({scenario});
|
|
79
79
|
* })();
|
|
80
80
|
* ```
|
|
81
81
|
*/
|
|
82
82
|
function run(runOptions = {}) {
|
|
83
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
const config =
|
|
85
|
-
setConfigByRunOptions(config, runOptions);
|
|
84
|
+
const config = getConfigFromRunOptions(runOptions);
|
|
86
85
|
config.externalCookiesFile = runOptions.cookiesFile;
|
|
87
86
|
config.scenario = runOptions.scenario;
|
|
88
87
|
const testPlanner = new e2e_1.TestPlanner({ config });
|
|
@@ -90,7 +89,8 @@ function run(runOptions = {}) {
|
|
|
90
89
|
yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
91
90
|
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
92
91
|
const runResult = BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
93
|
-
|
|
92
|
+
const leaks = yield findLeaks(runResult);
|
|
93
|
+
return { leaks, runResult };
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
exports.run = run;
|
|
@@ -99,7 +99,7 @@ exports.run = run;
|
|
|
99
99
|
* This is equivalent to run `memlab snapshot` in CLI.
|
|
100
100
|
*
|
|
101
101
|
* @param options configure browser interaction run
|
|
102
|
-
* @returns browser interaction results
|
|
102
|
+
* @returns a utility reading browser interaction results from disk
|
|
103
103
|
* * **Examples**:
|
|
104
104
|
* ```javascript
|
|
105
105
|
* const {takeSnapshots} = require('@memlab/api');
|
|
@@ -114,8 +114,7 @@ exports.run = run;
|
|
|
114
114
|
*/
|
|
115
115
|
function takeSnapshots(options = {}) {
|
|
116
116
|
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
-
const config =
|
|
118
|
-
setConfigByRunOptions(config, options);
|
|
117
|
+
const config = getConfigFromRunOptions(options);
|
|
119
118
|
config.externalCookiesFile = options.cookiesFile;
|
|
120
119
|
config.scenario = options.scenario;
|
|
121
120
|
const testPlanner = new e2e_1.TestPlanner();
|
|
@@ -232,8 +231,16 @@ function warmup(options = {}) {
|
|
|
232
231
|
});
|
|
233
232
|
}
|
|
234
233
|
exports.warmup = warmup;
|
|
235
|
-
function
|
|
234
|
+
function getConfigFromRunOptions(options) {
|
|
235
|
+
let config = core_1.MemLabConfig.getInstance();
|
|
236
|
+
if (options.workDir) {
|
|
237
|
+
core_1.fileManager.initDirs(config, { workDir: options.workDir });
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
241
|
+
}
|
|
236
242
|
config.isFullRun = !!options.snapshotForEachStep;
|
|
243
|
+
return config;
|
|
237
244
|
}
|
|
238
245
|
function setupPage(page, options = {}) {
|
|
239
246
|
var _a, _b, _c;
|
|
@@ -43,7 +43,7 @@ function inject() {
|
|
|
43
43
|
}
|
|
44
44
|
function test() {
|
|
45
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
-
const leaks = yield (0, index_1.run)({ scenario, evalInBrowserAfterInitLoad: inject });
|
|
46
|
+
const { leaks } = yield (0, index_1.run)({ scenario, evalInBrowserAfterInitLoad: inject });
|
|
47
47
|
core_1.info.lowLevel(`${leaks.length}`);
|
|
48
48
|
});
|
|
49
49
|
}
|
|
@@ -17,7 +17,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
20
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
const os_1 = __importDefault(require("os"));
|
|
25
|
+
const path_1 = __importDefault(require("path"));
|
|
26
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
21
27
|
const index_1 = require("../../index");
|
|
22
28
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
23
29
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -41,12 +47,12 @@ function injectDetachedDOMElements() {
|
|
|
41
47
|
};
|
|
42
48
|
}
|
|
43
49
|
test('leak detector can find detached DOM elements', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
-
const leaks = yield (0, index_1.run)({
|
|
50
|
+
const { leaks } = yield (0, index_1.run)({
|
|
45
51
|
scenario: E2ETestSettings_1.scenario,
|
|
46
52
|
evalInBrowserAfterInitLoad: injectDetachedDOMElements,
|
|
47
53
|
});
|
|
48
54
|
// detected all different leak trace cluster
|
|
49
|
-
expect(leaks.length).toBe(
|
|
55
|
+
expect(leaks.length >= 1).toBe(true);
|
|
50
56
|
// expect all traces are found
|
|
51
57
|
expect(leaks.some(leak => JSON.stringify(leak).includes('__injectedValue')));
|
|
52
58
|
expect(leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
|
|
@@ -61,12 +67,17 @@ test('self-defined leak detector can find TestObject', () => __awaiter(void 0, v
|
|
|
61
67
|
return node.name === 'TestObject' && node.type === 'object';
|
|
62
68
|
},
|
|
63
69
|
};
|
|
64
|
-
const
|
|
70
|
+
const workDir = path_1.default.join(os_1.default.tmpdir(), 'memlab-api-test', `${process.pid}`);
|
|
71
|
+
fs_extra_1.default.mkdirsSync(workDir);
|
|
72
|
+
const result = yield (0, index_1.run)({
|
|
65
73
|
scenario: selfDefinedScenario,
|
|
66
74
|
evalInBrowserAfterInitLoad: injectDetachedDOMElements,
|
|
75
|
+
workDir,
|
|
67
76
|
});
|
|
68
77
|
// detected all different leak trace cluster
|
|
69
|
-
expect(leaks.length).toBe(1);
|
|
78
|
+
expect(result.leaks.length).toBe(1);
|
|
70
79
|
// expect all traces are found
|
|
71
|
-
expect(leaks.some(leak => JSON.stringify(leak).includes('_randomObject')));
|
|
80
|
+
expect(result.leaks.some(leak => JSON.stringify(leak).includes('_randomObject')));
|
|
81
|
+
const reader = result.runResult;
|
|
82
|
+
expect(path_1.default.resolve(reader.getRootDirectory())).toBe(path_1.default.resolve(workDir));
|
|
72
83
|
}), E2ETestSettings_1.testTimeout);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-1.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
class TestObject {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.arr1 = [1, 2, 3];
|
|
25
|
+
this.arr2 = ['1', '2', '3'];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
(function () {
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
|
+
const obj = new TestObject();
|
|
32
|
+
// get a heap snapshot of the current program state
|
|
33
|
+
const heap = yield (0, core_1.getNodeInnocentHeap)();
|
|
34
|
+
const node = heap.getAnyObjectWithClassName('TestObject');
|
|
35
|
+
console.log(node === null || node === void 0 ? void 0 : node.name);
|
|
36
|
+
});
|
|
37
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-2.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
23
|
+
(function () {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
26
|
+
const heap = yield (0, heap_analysis_1.getHeapFromFile)(heapFile);
|
|
27
|
+
// get the total number of heap objects
|
|
28
|
+
heap.nodes.length;
|
|
29
|
+
heap.nodes.forEach((node) => {
|
|
30
|
+
console.log(node.name);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-3.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
23
|
+
(function () {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
26
|
+
const heap = yield (0, heap_analysis_1.getHeapFromFile)(heapFile);
|
|
27
|
+
// get the total number of heap references
|
|
28
|
+
heap.edges.length;
|
|
29
|
+
heap.edges.forEach((edge) => {
|
|
30
|
+
console.log(edge.name_or_index);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-4.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
23
|
+
(function () {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
26
|
+
const heap = yield (0, heap_analysis_1.getHeapFromFile)(heapFile);
|
|
27
|
+
const node = heap.getNodeById(1);
|
|
28
|
+
if (node) {
|
|
29
|
+
console.log(node.id);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-5.test.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
class TestObject {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.arr1 = [1, 2, 3];
|
|
25
|
+
this.arr2 = ['1', '2', '3'];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
test('memory test', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
core_1.config.muteConsole = true;
|
|
30
|
+
let obj = new TestObject();
|
|
31
|
+
// get a heap snapshot of the current program state
|
|
32
|
+
let heap = yield (0, core_1.getNodeInnocentHeap)();
|
|
33
|
+
// call some function that may add references to obj
|
|
34
|
+
// rabbitHole()
|
|
35
|
+
expect(heap.hasObjectWithClassName('TestObject')).toBe(true);
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
37
|
+
obj = null;
|
|
38
|
+
heap = yield (0, core_1.getNodeInnocentHeap)();
|
|
39
|
+
// if rabbitHole does not add new references, the obj can be GCed
|
|
40
|
+
expect(heap.hasObjectWithClassName('TestObject')).toBe(false);
|
|
41
|
+
}), 30000);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-6.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
const heap_analysis_1 = require("@memlab/heap-analysis");
|
|
23
|
+
(function () {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
+
const object = { 'memlab-test-heap-property': 'memlab-test-heap-value' };
|
|
27
|
+
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
28
|
+
const heap = yield (0, heap_analysis_1.getHeapFromFile)(heapFile);
|
|
29
|
+
// should be true
|
|
30
|
+
console.log(heap.hasObjectWithPropertyName('memlab-test-heap-property'));
|
|
31
|
+
});
|
|
32
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=example-7.test.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
test('memory test', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
core_1.config.muteConsole = true;
|
|
24
|
+
const o1 = {};
|
|
25
|
+
let o2 = {};
|
|
26
|
+
// tag o1 with marker: "memlab-mark-1"
|
|
27
|
+
(0, core_1.tagObject)(o1, 'memlab-mark-1');
|
|
28
|
+
// tag o2 with marker: "memlab-mark-2"
|
|
29
|
+
(0, core_1.tagObject)(o2, 'memlab-mark-2');
|
|
30
|
+
o2 = null;
|
|
31
|
+
const heap = yield (0, core_1.getNodeInnocentHeap)();
|
|
32
|
+
// expect object with marker "memlab-mark-1" exists
|
|
33
|
+
expect(heap.hasObjectWithTag('memlab-mark-1')).toBe(true);
|
|
34
|
+
// expect object with marker "memlab-mark-2" can be GCed
|
|
35
|
+
expect(heap.hasObjectWithTag('memlab-mark-2')).toBe(false);
|
|
36
|
+
}), 30000);
|
package/dist/index.d.ts
CHANGED
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
* @emails oncall+ws_labs
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
|
+
/** @internal */
|
|
11
|
+
export declare function registerPackage(): Promise<void>;
|
|
10
12
|
export * from './API';
|
|
11
13
|
export * from '@memlab/heap-analysis';
|
|
12
14
|
export { default as BrowserInteractionResultReader } from './result-reader/BrowserInteractionResultReader';
|
|
13
|
-
export { dumpNodeHeapSnapshot,
|
|
15
|
+
export { dumpNodeHeapSnapshot, getNodeInnocentHeap } from '@memlab/core';
|
|
14
16
|
/** @internal */
|
|
15
17
|
export { config } from '@memlab/core';
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -22,18 +22,36 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
22
22
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
23
23
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
24
24
|
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
25
34
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
36
|
};
|
|
28
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.config = exports.
|
|
38
|
+
exports.config = exports.getNodeInnocentHeap = exports.dumpNodeHeapSnapshot = exports.BrowserInteractionResultReader = exports.registerPackage = void 0;
|
|
39
|
+
const path_1 = __importDefault(require("path"));
|
|
40
|
+
const core_1 = require("@memlab/core");
|
|
41
|
+
/** @internal */
|
|
42
|
+
function registerPackage() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
return core_1.PackageInfoLoader.registerPackage(path_1.default.join(__dirname, '..'));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
exports.registerPackage = registerPackage;
|
|
30
48
|
__exportStar(require("./API"), exports);
|
|
31
49
|
__exportStar(require("@memlab/heap-analysis"), exports);
|
|
32
50
|
var BrowserInteractionResultReader_1 = require("./result-reader/BrowserInteractionResultReader");
|
|
33
51
|
Object.defineProperty(exports, "BrowserInteractionResultReader", { enumerable: true, get: function () { return __importDefault(BrowserInteractionResultReader_1).default; } });
|
|
34
|
-
var core_1 = require("@memlab/core");
|
|
35
|
-
Object.defineProperty(exports, "dumpNodeHeapSnapshot", { enumerable: true, get: function () { return core_1.dumpNodeHeapSnapshot; } });
|
|
36
|
-
Object.defineProperty(exports, "getCurrentNodeHeap", { enumerable: true, get: function () { return core_1.getCurrentNodeHeap; } });
|
|
37
|
-
/** @internal */
|
|
38
52
|
var core_2 = require("@memlab/core");
|
|
39
|
-
Object.defineProperty(exports, "
|
|
53
|
+
Object.defineProperty(exports, "dumpNodeHeapSnapshot", { enumerable: true, get: function () { return core_2.dumpNodeHeapSnapshot; } });
|
|
54
|
+
Object.defineProperty(exports, "getNodeInnocentHeap", { enumerable: true, get: function () { return core_2.getNodeInnocentHeap; } });
|
|
55
|
+
/** @internal */
|
|
56
|
+
var core_3 = require("@memlab/core");
|
|
57
|
+
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return core_3.config; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memlab/api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "memlab API",
|
|
6
6
|
"author": "Liang Gong <lgong@fb.com>",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@memlab/core": "^1.
|
|
30
|
-
"@memlab/e2e": "^1.0.
|
|
31
|
-
"@memlab/heap-analysis": "^1.0.
|
|
29
|
+
"@memlab/core": "^1.1.6",
|
|
30
|
+
"@memlab/e2e": "^1.0.7",
|
|
31
|
+
"@memlab/heap-analysis": "^1.0.5",
|
|
32
32
|
"ansi": "^0.3.1",
|
|
33
33
|
"babar": "^0.2.0",
|
|
34
34
|
"chalk": "^4.0.0",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build-pkg": "tsc",
|
|
59
59
|
"test-pkg": "jest .",
|
|
60
|
+
"publish-patch": "npm version patch --force && npm publish",
|
|
60
61
|
"clean-pkg": "rm -rf ./dist && rm -rf ./node_modules && rm -f ./tsconfig.tsbuildinfo"
|
|
61
62
|
},
|
|
62
63
|
"bugs": {
|