@memlab/api 1.0.2 → 1.0.5

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.
Files changed (47) hide show
  1. package/README.md +3 -2
  2. package/dist/API.d.ts +108 -19
  3. package/dist/API.js +89 -23
  4. package/dist/__tests__/API/E2EFindLeaks.example.js +1 -1
  5. package/dist/__tests__/API/E2EFindMemoryLeaks.test.js +35 -3
  6. package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.js +4 -2
  7. package/dist/__tests__/heap/examples/example-1.d.ts +11 -0
  8. package/dist/__tests__/heap/examples/example-1.js +37 -0
  9. package/dist/__tests__/heap/examples/example-2.d.ts +11 -0
  10. package/dist/__tests__/heap/examples/example-2.js +33 -0
  11. package/dist/__tests__/heap/examples/example-3.d.ts +11 -0
  12. package/dist/__tests__/heap/examples/example-3.js +33 -0
  13. package/dist/__tests__/heap/examples/example-4.d.ts +11 -0
  14. package/dist/__tests__/heap/examples/example-4.js +32 -0
  15. package/dist/__tests__/heap/examples/example-5.test.d.ts +11 -0
  16. package/dist/__tests__/heap/examples/example-5.test.js +41 -0
  17. package/dist/__tests__/heap/examples/example-6.d.ts +11 -0
  18. package/dist/__tests__/heap/examples/example-6.js +32 -0
  19. package/dist/__tests__/heap/examples/example-7.test.d.ts +11 -0
  20. package/dist/__tests__/heap/examples/example-7.test.js +36 -0
  21. package/dist/__tests__/packages/heap-analysis.test.d.ts +11 -0
  22. package/dist/__tests__/packages/heap-analysis.test.js +82 -0
  23. package/dist/index.d.ts +5 -1
  24. package/dist/index.js +25 -3
  25. package/dist/result-reader/BaseResultReader.d.ts +30 -9
  26. package/dist/result-reader/BaseResultReader.js +30 -6
  27. package/dist/result-reader/BrowserInteractionResultReader.d.ts +64 -5
  28. package/dist/result-reader/BrowserInteractionResultReader.js +64 -5
  29. package/package.json +3 -2
  30. package/dist/API.d.ts.map +0 -1
  31. package/dist/__tests__/API/E2EBasicAnalysis.test.d.ts.map +0 -1
  32. package/dist/__tests__/API/E2EDetachedDOMAnalysis.test.d.ts.map +0 -1
  33. package/dist/__tests__/API/E2EDuplicateObjectAnalysis.test.d.ts.map +0 -1
  34. package/dist/__tests__/API/E2EFindLeaks.example.d.ts.map +0 -1
  35. package/dist/__tests__/API/E2EFindMemoryLeaks.test.d.ts.map +0 -1
  36. package/dist/__tests__/API/E2EResultReader.test.d.ts.map +0 -1
  37. package/dist/__tests__/API/E2ERunMultipleSnapshots.example.d.ts.map +0 -1
  38. package/dist/__tests__/API/E2ERunSingleSnapshot.example.d.ts.map +0 -1
  39. package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.d.ts.map +0 -1
  40. package/dist/__tests__/API/E2EStringAnalysis.test.d.ts.map +0 -1
  41. package/dist/__tests__/API/lib/E2ETestSettings.d.ts.map +0 -1
  42. package/dist/__tests__/heap/E2EHeapParser.test.d.ts.map +0 -1
  43. package/dist/__tests__/heap/lib/HeapParserTestUtils.d.ts.map +0 -1
  44. package/dist/index.d.ts.map +0 -1
  45. package/dist/lib/APIUtils.d.ts.map +0 -1
  46. package/dist/result-reader/BaseResultReader.d.ts.map +0 -1
  47. package/dist/result-reader/BrowserInteractionResultReader.d.ts.map +0 -1
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
- ## Full documentation
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
@@ -8,20 +8,26 @@
8
8
  * @format
9
9
  */
10
10
  import type { ParsedArgs } from 'minimist';
11
- import type { AnyFunction, AnyValue, ISerializedInfo, IScenario } from '@memlab/core';
11
+ import type { AnyFunction, ISerializedInfo, IScenario } from '@memlab/core';
12
12
  import { MemLabConfig } from '@memlab/core';
13
13
  import { TestPlanner } from '@memlab/e2e';
14
14
  import { BaseAnalysis } from '@memlab/heap-analysis';
15
15
  import BrowserInteractionResultReader from './result-reader/BrowserInteractionResultReader';
16
16
  /**
17
- * Options for configuring browser interaction run
17
+ * Options for configuring browser interaction run, all fields are optional
18
18
  */
19
19
  export declare type RunOptions = {
20
- /** test scenario definition */
20
+ /**
21
+ * test scenario specifying how to interact with browser
22
+ * (for more details view {@link IScenario})
23
+ */
21
24
  scenario?: IScenario;
22
- /** cookies file */
25
+ /** the absolute path of cookies file */
23
26
  cookiesFile?: string;
24
- /** function to be evaluated in browser context after the web page initial load */
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,10 +35,33 @@ 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
- * @ignore
35
63
  * Options for memlab inter-package API calls
64
+ * @internal
36
65
  */
37
66
  export declare type APIOptions = {
38
67
  testPlanner?: TestPlanner;
@@ -43,29 +72,62 @@ export declare type APIOptions = {
43
72
  /**
44
73
  * This API warms up web server, runs E2E interaction, and takes heap snapshots.
45
74
  * This is equivalent to run `memlab warmup-and-snapshot` in CLI.
46
- * This is also equivalent to call {@link warmup} and {@link takeSnapshots}.
75
+ * This is also equivalent to warm up and call {@link takeSnapshots}.
47
76
  *
48
77
  * @param options configure browser interaction run
49
78
  * @returns browser interaction results
79
+ * * **Examples**:
80
+ * ```javascript
81
+ * const {warmupAndTakeSnapshots} = require('@memlab/api');
82
+ *
83
+ * (async function () {
84
+ * const scenario = {
85
+ * url: () => 'https://www.facebook.com',
86
+ * };
87
+ * const result = await warmupAndTakeSnapshots({scenario});
88
+ * })();
89
+ * ```
50
90
  */
51
91
  export declare function warmupAndTakeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
52
92
  /**
53
93
  * This API runs browser interaction and find memory leaks triggered in browser
54
94
  * This is equivalent to run `memlab run` in CLI.
55
- * This is also equivalent to call {@link warmup}, {@link takeSnapshots},
95
+ * This is also equivalent to warm up, and call {@link takeSnapshots}
56
96
  * and {@link findLeaks}.
57
97
  *
58
- * @param options configure browser interaction run
59
- * @returns an array of leak traces detected and clustered from the
60
- * browser interaction
98
+ * @param runOptions configure browser interaction run
99
+ * @returns memory leaks detected and a utility reading browser
100
+ * interaction results from disk
101
+ * * **Examples**:
102
+ * ```javascript
103
+ * const {run} = require('@memlab/api');
104
+ *
105
+ * (async function () {
106
+ * const scenario = {
107
+ * url: () => 'https://www.facebook.com',
108
+ * };
109
+ * const {leaks} = await run({scenario});
110
+ * })();
111
+ * ```
61
112
  */
62
- export declare function run(options?: RunOptions): Promise<ISerializedInfo[]>;
113
+ export declare function run(runOptions?: RunOptions): Promise<RunResult>;
63
114
  /**
64
115
  * This API runs E2E interaction and takes heap snapshots.
65
116
  * This is equivalent to run `memlab snapshot` in CLI.
66
117
  *
67
118
  * @param options configure browser interaction run
68
- * @returns browser interaction results
119
+ * @returns a utility reading browser interaction results from disk
120
+ * * **Examples**:
121
+ * ```javascript
122
+ * const {takeSnapshots} = require('@memlab/api');
123
+ *
124
+ * (async function () {
125
+ * const scenario = {
126
+ * url: () => 'https://www.facebook.com',
127
+ * };
128
+ * const result = await takeSnapshots({scenario});
129
+ * })();
130
+ * ```
69
131
  */
70
132
  export declare function takeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
71
133
  /**
@@ -73,8 +135,19 @@ export declare function takeSnapshots(options?: RunOptions): Promise<BrowserInte
73
135
  * This is equivalent to `memlab find-leaks` in CLI.
74
136
  *
75
137
  * @param runResult return value of a browser interaction run
76
- * @returns an array of leak traces detected and clustered from the
77
- * browser interaction
138
+ * @returns leak traces detected and clustered from the browser interaction
139
+ * * **Examples**:
140
+ * ```javascript
141
+ * const {findLeaks, takeSnapshots} = require('@memlab/api');
142
+ *
143
+ * (async function () {
144
+ * const scenario = {
145
+ * url: () => 'https://www.facebook.com',
146
+ * };
147
+ * const result = await takeSnapshots({scenario});
148
+ * const leaks = findLeaks(result);
149
+ * })();
150
+ * ```
78
151
  */
79
152
  export declare function findLeaks(runResult: BrowserInteractionResultReader): Promise<ISerializedInfo[]>;
80
153
  /**
@@ -84,19 +157,35 @@ export declare function findLeaks(runResult: BrowserInteractionResultReader): Pr
84
157
  * @param runResult return value of a browser interaction run
85
158
  * @param heapAnalyzer instance of a heap analysis
86
159
  * @param args other CLI arguments that needs to be passed to the heap analysis
87
- * @returns
160
+ * @returns each analysis may have a different return type, please check out
161
+ * the type definition or the documentation for the `process` method of the
162
+ * analysis class you are using for `heapAnalyzer`.
163
+ * * **Examples**:
164
+ * ```javascript
165
+ * const {takeSnapshots, StringAnalysis} = require('@memlab/api');
166
+ *
167
+ * (async function () {
168
+ * const scenario = {
169
+ * url: () => 'https://www.facebook.com',
170
+ * };
171
+ * const result = await takeSnapshots({scenario});
172
+ * const analysis = new StringAnalysis();
173
+ * await analyze(result, analysis);
174
+ * })();
175
+ * ```
88
176
  */
89
- export declare function analyze(runResult: BrowserInteractionResultReader, heapAnalyzer: BaseAnalysis, args?: ParsedArgs): Promise<AnyValue>;
177
+ export declare function analyze(runResult: BrowserInteractionResultReader, heapAnalyzer: BaseAnalysis, args?: ParsedArgs): Promise<void>;
90
178
  /**
91
- * @ignore
92
179
  * This warms up web server by sending web requests to the web sever.
93
180
  * This is equivalent to run `memlab warmup` in CLI.
181
+ * @internal
94
182
  *
95
183
  * @param options configure browser interaction run
96
184
  */
97
185
  export declare function warmup(options?: APIOptions): Promise<void>;
98
186
  /**
99
- * @ignore
187
+ * Browser interaction API used by MemLab API and MemLab CLI
188
+ * @internal
100
189
  */
101
190
  export declare function testInBrowser(options?: APIOptions): Promise<void>;
102
191
  //# sourceMappingURL=API.d.ts.map
package/dist/API.js CHANGED
@@ -29,15 +29,25 @@ const BrowserInteractionResultReader_1 = __importDefault(require("./result-reade
29
29
  /**
30
30
  * This API warms up web server, runs E2E interaction, and takes heap snapshots.
31
31
  * This is equivalent to run `memlab warmup-and-snapshot` in CLI.
32
- * This is also equivalent to call {@link warmup} and {@link takeSnapshots}.
32
+ * This is also equivalent to warm up and call {@link takeSnapshots}.
33
33
  *
34
34
  * @param options configure browser interaction run
35
35
  * @returns browser interaction results
36
+ * * **Examples**:
37
+ * ```javascript
38
+ * const {warmupAndTakeSnapshots} = require('@memlab/api');
39
+ *
40
+ * (async function () {
41
+ * const scenario = {
42
+ * url: () => 'https://www.facebook.com',
43
+ * };
44
+ * const result = await warmupAndTakeSnapshots({scenario});
45
+ * })();
46
+ * ```
36
47
  */
37
48
  function warmupAndTakeSnapshots(options = {}) {
38
49
  return __awaiter(this, void 0, void 0, function* () {
39
- const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
40
- setConfigByRunOptions(config, options);
50
+ const config = getConfigFromRunOptions(options);
41
51
  config.externalCookiesFile = options.cookiesFile;
42
52
  config.scenario = options.scenario;
43
53
  const testPlanner = new e2e_1.TestPlanner({ config });
@@ -51,25 +61,36 @@ exports.warmupAndTakeSnapshots = warmupAndTakeSnapshots;
51
61
  /**
52
62
  * This API runs browser interaction and find memory leaks triggered in browser
53
63
  * This is equivalent to run `memlab run` in CLI.
54
- * This is also equivalent to call {@link warmup}, {@link takeSnapshots},
64
+ * This is also equivalent to warm up, and call {@link takeSnapshots}
55
65
  * and {@link findLeaks}.
56
66
  *
57
- * @param options configure browser interaction run
58
- * @returns an array of leak traces detected and clustered from the
59
- * browser interaction
67
+ * @param runOptions configure browser interaction run
68
+ * @returns memory leaks detected and a utility reading browser
69
+ * interaction results from disk
70
+ * * **Examples**:
71
+ * ```javascript
72
+ * const {run} = require('@memlab/api');
73
+ *
74
+ * (async function () {
75
+ * const scenario = {
76
+ * url: () => 'https://www.facebook.com',
77
+ * };
78
+ * const {leaks} = await run({scenario});
79
+ * })();
80
+ * ```
60
81
  */
61
- function run(options = {}) {
82
+ function run(runOptions = {}) {
62
83
  return __awaiter(this, void 0, void 0, function* () {
63
- const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
64
- setConfigByRunOptions(config, options);
65
- config.externalCookiesFile = options.cookiesFile;
66
- config.scenario = options.scenario;
84
+ const config = getConfigFromRunOptions(runOptions);
85
+ config.externalCookiesFile = runOptions.cookiesFile;
86
+ config.scenario = runOptions.scenario;
67
87
  const testPlanner = new e2e_1.TestPlanner({ config });
68
- const { evalInBrowserAfterInitLoad } = options;
88
+ const { evalInBrowserAfterInitLoad } = runOptions;
69
89
  yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
70
90
  yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
71
91
  const runResult = BrowserInteractionResultReader_1.default.from(config.workDir);
72
- return yield findLeaks(runResult);
92
+ const leaks = yield findLeaks(runResult);
93
+ return { leaks, runResult };
73
94
  });
74
95
  }
75
96
  exports.run = run;
@@ -78,12 +99,22 @@ exports.run = run;
78
99
  * This is equivalent to run `memlab snapshot` in CLI.
79
100
  *
80
101
  * @param options configure browser interaction run
81
- * @returns browser interaction results
102
+ * @returns a utility reading browser interaction results from disk
103
+ * * **Examples**:
104
+ * ```javascript
105
+ * const {takeSnapshots} = require('@memlab/api');
106
+ *
107
+ * (async function () {
108
+ * const scenario = {
109
+ * url: () => 'https://www.facebook.com',
110
+ * };
111
+ * const result = await takeSnapshots({scenario});
112
+ * })();
113
+ * ```
82
114
  */
83
115
  function takeSnapshots(options = {}) {
84
116
  return __awaiter(this, void 0, void 0, function* () {
85
- const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
86
- setConfigByRunOptions(config, options);
117
+ const config = getConfigFromRunOptions(options);
87
118
  config.externalCookiesFile = options.cookiesFile;
88
119
  config.scenario = options.scenario;
89
120
  const testPlanner = new e2e_1.TestPlanner();
@@ -98,8 +129,19 @@ exports.takeSnapshots = takeSnapshots;
98
129
  * This is equivalent to `memlab find-leaks` in CLI.
99
130
  *
100
131
  * @param runResult return value of a browser interaction run
101
- * @returns an array of leak traces detected and clustered from the
102
- * browser interaction
132
+ * @returns leak traces detected and clustered from the browser interaction
133
+ * * **Examples**:
134
+ * ```javascript
135
+ * const {findLeaks, takeSnapshots} = require('@memlab/api');
136
+ *
137
+ * (async function () {
138
+ * const scenario = {
139
+ * url: () => 'https://www.facebook.com',
140
+ * };
141
+ * const result = await takeSnapshots({scenario});
142
+ * const leaks = findLeaks(result);
143
+ * })();
144
+ * ```
103
145
  */
104
146
  function findLeaks(runResult) {
105
147
  return __awaiter(this, void 0, void 0, function* () {
@@ -117,7 +159,22 @@ exports.findLeaks = findLeaks;
117
159
  * @param runResult return value of a browser interaction run
118
160
  * @param heapAnalyzer instance of a heap analysis
119
161
  * @param args other CLI arguments that needs to be passed to the heap analysis
120
- * @returns
162
+ * @returns each analysis may have a different return type, please check out
163
+ * the type definition or the documentation for the `process` method of the
164
+ * analysis class you are using for `heapAnalyzer`.
165
+ * * **Examples**:
166
+ * ```javascript
167
+ * const {takeSnapshots, StringAnalysis} = require('@memlab/api');
168
+ *
169
+ * (async function () {
170
+ * const scenario = {
171
+ * url: () => 'https://www.facebook.com',
172
+ * };
173
+ * const result = await takeSnapshots({scenario});
174
+ * const analysis = new StringAnalysis();
175
+ * await analyze(result, analysis);
176
+ * })();
177
+ * ```
121
178
  */
122
179
  function analyze(runResult, heapAnalyzer, args = { _: [] }) {
123
180
  return __awaiter(this, void 0, void 0, function* () {
@@ -128,9 +185,9 @@ function analyze(runResult, heapAnalyzer, args = { _: [] }) {
128
185
  }
129
186
  exports.analyze = analyze;
130
187
  /**
131
- * @ignore
132
188
  * This warms up web server by sending web requests to the web sever.
133
189
  * This is equivalent to run `memlab warmup` in CLI.
190
+ * @internal
134
191
  *
135
192
  * @param options configure browser interaction run
136
193
  */
@@ -174,8 +231,16 @@ function warmup(options = {}) {
174
231
  });
175
232
  }
176
233
  exports.warmup = warmup;
177
- function setConfigByRunOptions(config, options) {
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
+ }
178
242
  config.isFullRun = !!options.snapshotForEachStep;
243
+ return config;
179
244
  }
180
245
  function setupPage(page, options = {}) {
181
246
  var _a, _b, _c;
@@ -221,7 +286,8 @@ function initBrowserInfoInConfig(browser, options = {}) {
221
286
  });
222
287
  }
223
288
  /**
224
- * @ignore
289
+ * Browser interaction API used by MemLab API and MemLab CLI
290
+ * @internal
225
291
  */
226
292
  function testInBrowser(options = {}) {
227
293
  var _a, _b;
@@ -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,14 +17,21 @@ 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 });
21
- /* eslint-disable @typescript-eslint/ban-ts-comment */
24
+ const os_1 = __importDefault(require("os"));
25
+ const path_1 = __importDefault(require("path"));
26
+ const fs_extra_1 = __importDefault(require("fs-extra"));
22
27
  const index_1 = require("../../index");
23
28
  const E2ETestSettings_1 = require("./lib/E2ETestSettings");
24
29
  beforeEach(E2ETestSettings_1.testSetup);
25
30
  function injectDetachedDOMElements() {
26
31
  // @ts-ignore
27
32
  window.injectHookForLink4 = () => {
33
+ class TestObject {
34
+ }
28
35
  const arr = [];
29
36
  for (let i = 0; i < 23; ++i) {
30
37
  arr.push(document.createElement('div'));
@@ -35,17 +42,42 @@ function injectDetachedDOMElements() {
35
42
  window._path_1 = { x: { y: document.createElement('div') } };
36
43
  // @ts-ignore
37
44
  window._path_2 = new Set([document.createElement('div')]);
45
+ // @ts-ignore
46
+ window._randomObject = [new TestObject()];
38
47
  };
39
48
  }
40
49
  test('leak detector can find detached DOM elements', () => __awaiter(void 0, void 0, void 0, function* () {
41
- const leaks = yield (0, index_1.run)({
50
+ const { leaks } = yield (0, index_1.run)({
42
51
  scenario: E2ETestSettings_1.scenario,
43
52
  evalInBrowserAfterInitLoad: injectDetachedDOMElements,
44
53
  });
45
54
  // detected all different leak trace cluster
46
- expect(leaks.length).toBe(3);
55
+ expect(leaks.length >= 1).toBe(true);
47
56
  // expect all traces are found
48
57
  expect(leaks.some(leak => JSON.stringify(leak).includes('__injectedValue')));
49
58
  expect(leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
50
59
  expect(leaks.some(leak => JSON.stringify(leak).includes('_path_2')));
51
60
  }), E2ETestSettings_1.testTimeout);
61
+ test('self-defined leak detector can find TestObject', () => __awaiter(void 0, void 0, void 0, function* () {
62
+ const selfDefinedScenario = {
63
+ app: () => 'test-spa',
64
+ url: () => '',
65
+ action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
66
+ leakFilter: (node) => {
67
+ return node.name === 'TestObject' && node.type === 'object';
68
+ },
69
+ };
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)({
73
+ scenario: selfDefinedScenario,
74
+ evalInBrowserAfterInitLoad: injectDetachedDOMElements,
75
+ workDir,
76
+ });
77
+ // detected all different leak trace cluster
78
+ expect(result.leaks.length).toBe(1);
79
+ // expect all traces are found
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));
83
+ }), E2ETestSettings_1.testTimeout);
@@ -47,12 +47,14 @@ test('Shape unbound analysis works as expected', () => __awaiter(void 0, void 0,
47
47
  });
48
48
  // test analysis from auto loading
49
49
  let analysis = new index_1.ShapeUnboundGrowthAnalysis();
50
- let shapeSummary = yield analysis.run();
50
+ yield analysis.run();
51
+ let shapeSummary = analysis.getShapesWithUnboundGrowth();
51
52
  expect(shapeSummary.reduce((acc, summary) => acc || summary.shape.includes('LeakObject'), false)).toBe(true);
52
53
  // test analysis from file
53
54
  const snapshotDir = result.getSnapshotFileDir();
54
55
  analysis = new index_1.ShapeUnboundGrowthAnalysis();
55
- shapeSummary = yield analysis.analyzeSnapshotsInDirectory(snapshotDir);
56
+ yield analysis.analyzeSnapshotsInDirectory(snapshotDir);
57
+ shapeSummary = analysis.getShapesWithUnboundGrowth();
56
58
  expect(shapeSummary.some((summary) => summary.shape.includes('LeakObject'))).toBe(true);
57
59
  // expect incorrect use of heap analysis to throw
58
60
  const snapshotFile = result.getSnapshotFiles().pop();
@@ -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