@memlab/api 2.0.3 → 2.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.
package/dist/API.js CHANGED
@@ -127,7 +127,7 @@ function takeSnapshots() {
127
127
  return __awaiter(this, arguments, void 0, function* (options = {}) {
128
128
  const config = getConfigFromRunOptions(options);
129
129
  const state = APIStateManager_1.default.getAndUpdateState(config, options);
130
- const testPlanner = new e2e_1.TestPlanner();
130
+ const testPlanner = new e2e_1.TestPlanner({ config });
131
131
  const { evalInBrowserAfterInitLoad } = options;
132
132
  yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
133
133
  const ret = BrowserInteractionResultReader_1.default.from(config.workDir);
@@ -287,9 +287,9 @@ function getConfigFromRunOptions(options) {
287
287
  if ('webWorker' in options) {
288
288
  config.isAnalyzingMainThread = false;
289
289
  const value = options.webWorker;
290
- if (typeof value === 'string') {
291
- config.targetWorkerTitle = value;
292
- }
290
+ // config is a singleton shared by all API calls in the process, so the
291
+ // title has to be cleared when this run targets any web worker
292
+ config.targetWorkerTitle = typeof value === 'string' ? value : null;
293
293
  }
294
294
  else {
295
295
  config.isAnalyzingMainThread = true;
@@ -27,6 +27,9 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
27
27
  const index_1 = require("../../index");
28
28
  const E2ETestSettings_1 = require("./lib/E2ETestSettings");
29
29
  beforeEach(E2ETestSettings_1.testSetup);
30
+ function hasPathEdgeWithName(leak, edgeName) {
31
+ return Object.keys(leak).some(key => key.includes(`--${edgeName} (`));
32
+ }
30
33
  function injectDetachedDOMElements() {
31
34
  // @ts-ignore
32
35
  window.injectHookForLink4 = () => {
@@ -74,8 +77,11 @@ test('self-defined retainer trace filter work as expected (part 1)', () => __awa
74
77
  app: () => 'test-spa',
75
78
  url: () => '',
76
79
  action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
77
- retainerReferenceFilter: (edge) => {
78
- return edge.name_or_index !== '_path_1';
80
+ retainerReferenceFilter: (edge, _snapshot, isReferenceUsedByDefault) => {
81
+ if (edge.name_or_index === '_path_1') {
82
+ return false;
83
+ }
84
+ return isReferenceUsedByDefault;
79
85
  },
80
86
  };
81
87
  const workDir = path_1.default.join(os_1.default.tmpdir(), 'memlab-api-test', (0, E2ETestSettings_1.getUniqueID)());
@@ -85,12 +91,12 @@ test('self-defined retainer trace filter work as expected (part 1)', () => __awa
85
91
  evalInBrowserAfterInitLoad: injectDetachedDOMElements,
86
92
  workDir,
87
93
  });
88
- // detected all different leak trace cluster
89
- expect(result.leaks.length).toBe(1);
90
- // expect the none of the traces to include _path_1
91
- expect(result.leaks.every(leak => !JSON.stringify(leak).includes('_path_1')));
92
- // expect some of the traces to include _path_2
93
- expect(result.leaks.some(leak => JSON.stringify(leak).includes('_path_2')));
94
+ // detected leak trace clusters
95
+ expect(result.leaks.length).toBeGreaterThanOrEqual(1);
96
+ // expect none of the retainer trace paths to go through _path_1
97
+ expect(result.leaks.every(leak => !hasPathEdgeWithName(leak, '_path_1'))).toBe(true);
98
+ // expect some of the retainer trace paths to go through _path_2
99
+ expect(result.leaks.some(leak => hasPathEdgeWithName(leak, '_path_2'))).toBe(true);
94
100
  const reader = result.runResult;
95
101
  expect(path_1.default.resolve(reader.getRootDirectory())).toBe(path_1.default.resolve(workDir));
96
102
  }), E2ETestSettings_1.testTimeout);
@@ -99,8 +105,11 @@ test('self-defined retainer trace filter work as expected (part 2)', () => __awa
99
105
  app: () => 'test-spa',
100
106
  url: () => '',
101
107
  action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
102
- retainerReferenceFilter: (edge) => {
103
- return edge.name_or_index !== '_path_2';
108
+ retainerReferenceFilter: (edge, _snapshot, isReferenceUsedByDefault) => {
109
+ if (edge.name_or_index === '_path_2') {
110
+ return false;
111
+ }
112
+ return isReferenceUsedByDefault;
104
113
  },
105
114
  };
106
115
  const workDir = path_1.default.join(os_1.default.tmpdir(), 'memlab-api-test', (0, E2ETestSettings_1.getUniqueID)());
@@ -110,12 +119,12 @@ test('self-defined retainer trace filter work as expected (part 2)', () => __awa
110
119
  evalInBrowserAfterInitLoad: injectDetachedDOMElements,
111
120
  workDir,
112
121
  });
113
- // detected all different leak trace cluster
114
- expect(result.leaks.length).toBe(1);
115
- // expect the none of the traces to include _path_2
116
- expect(result.leaks.every(leak => !JSON.stringify(leak).includes('_path_2')));
117
- // expect some of the traces to include _path_1
118
- expect(result.leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
122
+ // detected leak trace clusters
123
+ expect(result.leaks.length).toBeGreaterThanOrEqual(1);
124
+ // expect none of the retainer trace paths to go through _path_2
125
+ expect(result.leaks.every(leak => !hasPathEdgeWithName(leak, '_path_2'))).toBe(true);
126
+ // expect some of the retainer trace paths to go through _path_1
127
+ expect(result.leaks.some(leak => hasPathEdgeWithName(leak, '_path_1'))).toBe(true);
119
128
  const reader = result.runResult;
120
129
  expect(path_1.default.resolve(reader.getRootDirectory())).toBe(path_1.default.resolve(workDir));
121
130
  }), E2ETestSettings_1.testTimeout);
@@ -53,9 +53,9 @@ function checkResultReader(result) {
53
53
  expect(runMeta.app).toBe('test-spa');
54
54
  result.cleanup();
55
55
  expect(fs_1.default.existsSync(workDir)).toBe(false);
56
- expect(() => result.getRootDirectory()).toThrowError();
57
- expect(() => result.getSnapshotFileDir()).toThrowError();
58
- expect(() => result.getSnapshotFiles()).toThrowError();
56
+ expect(() => result.getRootDirectory()).toThrow();
57
+ expect(() => result.getSnapshotFileDir()).toThrow();
58
+ expect(() => result.getSnapshotFiles()).toThrow();
59
59
  }
60
60
  test('result data/file reader is working as expected', () => __awaiter(void 0, void 0, void 0, function* () {
61
61
  const result = yield (0, index_1.warmupAndTakeSnapshots)({
@@ -84,7 +84,7 @@ function testIncorrectUseage(result) {
84
84
  // expect incorrect use of heap analysis to throw
85
85
  const snapshotFile = result.getSnapshotFiles().pop();
86
86
  const analysis = new index_1.ShapeUnboundGrowthAnalysis();
87
- expect(() => __awaiter(this, void 0, void 0, function* () { return yield analysis.analyzeSnapshotFromFile(snapshotFile); })).rejects.toThrowError();
87
+ expect(() => __awaiter(this, void 0, void 0, function* () { return yield analysis.analyzeSnapshotFromFile(snapshotFile); })).rejects.toThrow();
88
88
  });
89
89
  }
90
90
  function testAnalysisWithSpecifiedWorkDir(result) {
@@ -54,7 +54,7 @@ test('String analysis works as expected', () => __awaiter(void 0, void 0, void 0
54
54
  // expect incorrect use of heap analysis to throw
55
55
  const snapshotDir = result.getSnapshotFileDir();
56
56
  analysis = new index_1.StringAnalysis();
57
- expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotsInDirectory(snapshotDir); })).rejects.toThrowError();
57
+ expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotsInDirectory(snapshotDir); })).rejects.toThrow();
58
58
  }), E2ETestSettings_1.testTimeout);
59
59
  test('analyze function works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
60
60
  const result = yield (0, index_1.warmupAndTakeSnapshots)({
@@ -1 +1 @@
1
- {"version":3,"file":"HeapParserTestUtils.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/heap/lib/HeapParserTestUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAUhD,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,IAAI,EACxB,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,GACpD,OAAO,CAAC,IAAI,CAAC,CAGf"}
1
+ {"version":3,"file":"HeapParserTestUtils.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/heap/lib/HeapParserTestUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAWhD,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,IAAI,EACxB,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,GACpD,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -23,6 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.isExpectedSnapshot = isExpectedSnapshot;
25
25
  const fs_1 = __importDefault(require("fs"));
26
+ const os_1 = __importDefault(require("os"));
26
27
  const path_1 = __importDefault(require("path"));
27
28
  const core_1 = require("@memlab/core");
28
29
  const puppeteer = core_1.config.isFB
@@ -69,21 +70,27 @@ const TEST_URL = 'about:blank';
69
70
  function dumpHeap(snapshotFile, leakInjector) {
70
71
  return __awaiter(this, void 0, void 0, function* () {
71
72
  core_1.utils.tryToMutePuppeteerWarning();
72
- const browser = yield puppeteer.launch(core_1.config.puppeteerConfig);
73
- const page = yield browser.newPage();
74
- // set page size
75
- yield page.setViewport({
76
- width: 1680,
77
- height: 1050,
78
- deviceScaleFactor: 1,
79
- });
80
- // visit page
81
- yield page.goto(TEST_URL);
82
- // insert a memory leak object
83
- yield page.evaluate(leakInjector);
84
- // take a heap snapshot
85
- yield saveSnapshotToFile(page, snapshotFile);
86
- yield browser.close();
73
+ const userDataDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'memlab-heap-test-'));
74
+ try {
75
+ const browser = yield puppeteer.launch(Object.assign(Object.assign({}, core_1.config.puppeteerConfig), { userDataDir }));
76
+ const page = yield browser.newPage();
77
+ // set page size
78
+ yield page.setViewport({
79
+ width: 1680,
80
+ height: 1050,
81
+ deviceScaleFactor: 1,
82
+ });
83
+ // visit page
84
+ yield page.goto(TEST_URL);
85
+ // insert a memory leak object
86
+ yield page.evaluate(leakInjector);
87
+ // take a heap snapshot
88
+ yield saveSnapshotToFile(page, snapshotFile);
89
+ yield browser.close();
90
+ }
91
+ finally {
92
+ fs_1.default.rmSync(userDataDir, { recursive: true, force: true });
93
+ }
87
94
  });
88
95
  }
89
96
  let fileId = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memlab/api",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "license": "MIT",
5
5
  "description": "memlab API",
6
6
  "author": "Liang Gong <lgong@meta.com>",
@@ -27,16 +27,16 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@memlab/core": "^2.0.3",
31
- "@memlab/e2e": "^2.0.3",
32
- "@memlab/heap-analysis": "^2.0.3",
30
+ "@memlab/core": "^2.0.5",
31
+ "@memlab/e2e": "^2.0.5",
32
+ "@memlab/heap-analysis": "^2.0.5",
33
33
  "ansi": "^0.3.1",
34
34
  "babar": "^0.2.0",
35
35
  "chalk": "^4.0.0",
36
36
  "fs-extra": "^4.0.2",
37
37
  "minimist": "^1.2.8",
38
- "puppeteer": "^24.2.0",
39
- "puppeteer-core": "^24.2.0",
38
+ "puppeteer": "24.31.0",
39
+ "puppeteer-core": "24.31.0",
40
40
  "string-width": "^4.2.0",
41
41
  "util.promisify": "^1.1.1",
42
42
  "xvfb": "^0.4.0"