browsertime 16.16.0 → 17.0.0-beta.0

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 (121) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/bin/browsertime.js +43 -43
  3. package/bin/browsertimeWebPageReplay.js +10 -9
  4. package/browserscripts/pageinfo/generator.js +1 -1
  5. package/index.js +14 -13
  6. package/lib/android/gnirehtet.js +14 -15
  7. package/lib/android/index.js +92 -89
  8. package/lib/android/root.js +6 -9
  9. package/lib/chrome/chromeDevtoolsProtocol.js +46 -45
  10. package/lib/chrome/har.js +12 -13
  11. package/lib/chrome/longTaskMetrics.js +3 -5
  12. package/lib/chrome/parseCpuTrace.js +13 -10
  13. package/lib/chrome/settings/chromeAndroidOptions.js +1 -3
  14. package/lib/chrome/settings/chromeDesktopOptions.js +1 -3
  15. package/lib/chrome/settings/traceCategories.js +1 -3
  16. package/lib/chrome/traceCategoriesParser.js +35 -36
  17. package/lib/chrome/webdriver/builder.js +18 -26
  18. package/lib/chrome/webdriver/chromium.js +56 -46
  19. package/lib/chrome/webdriver/setupChromiumOptions.js +32 -27
  20. package/lib/connectivity/humble.js +13 -14
  21. package/lib/connectivity/index.js +74 -77
  22. package/lib/connectivity/trafficShapeParser.js +31 -35
  23. package/lib/core/engine/collector.js +25 -22
  24. package/lib/core/engine/command/addText.js +24 -27
  25. package/lib/core/engine/command/android.js +7 -11
  26. package/lib/core/engine/command/cache.js +3 -4
  27. package/lib/core/engine/command/chromeDevToolsProtocol.js +20 -20
  28. package/lib/core/engine/command/click.js +48 -49
  29. package/lib/core/engine/command/debug.js +3 -4
  30. package/lib/core/engine/command/javaScript.js +18 -19
  31. package/lib/core/engine/command/measure.js +31 -37
  32. package/lib/core/engine/command/meta.js +1 -4
  33. package/lib/core/engine/command/mouse/clickAndHold.js +36 -39
  34. package/lib/core/engine/command/mouse/contextClick.js +17 -18
  35. package/lib/core/engine/command/mouse/doubleClick.js +17 -19
  36. package/lib/core/engine/command/mouse/index.js +5 -9
  37. package/lib/core/engine/command/mouse/mouseMove.js +19 -23
  38. package/lib/core/engine/command/mouse/singleClick.js +15 -19
  39. package/lib/core/engine/command/navigation.js +12 -14
  40. package/lib/core/engine/command/screenshot.js +1 -4
  41. package/lib/core/engine/command/scroll.js +4 -7
  42. package/lib/core/engine/command/select.js +26 -26
  43. package/lib/core/engine/command/set.js +25 -23
  44. package/lib/core/engine/command/stopWatch.js +5 -8
  45. package/lib/core/engine/command/switch.js +18 -20
  46. package/lib/core/engine/command/util/lcpHighlightScript.js +1 -2
  47. package/lib/core/engine/command/util/lsHighlightScript.js +1 -2
  48. package/lib/core/engine/command/wait.js +18 -18
  49. package/lib/core/engine/index.js +81 -71
  50. package/lib/core/engine/iteration.js +93 -79
  51. package/lib/core/engine/run.js +5 -9
  52. package/lib/core/pageCompleteChecks/defaultPageCompleteCheck.js +1 -2
  53. package/lib/core/pageCompleteChecks/pageCompleteCheckByInactivity.js +1 -3
  54. package/lib/core/pageCompleteChecks/spaInactivity.js +1 -3
  55. package/lib/core/seleniumRunner.js +92 -100
  56. package/lib/core/webdriver/index.js +24 -21
  57. package/lib/edge/webdriver/builder.js +21 -26
  58. package/lib/extensionserver/httpServer.js +17 -21
  59. package/lib/extensionserver/index.js +8 -12
  60. package/lib/extensionserver/setup.js +12 -12
  61. package/lib/firefox/geckoProfiler.js +27 -21
  62. package/lib/firefox/getHAR.js +7 -8
  63. package/lib/firefox/memoryReport.js +9 -11
  64. package/lib/firefox/perfStats.js +5 -7
  65. package/lib/firefox/settings/disableSafeBrowsingPreferences.js +1 -3
  66. package/lib/firefox/settings/disableTrackingProtectionPreferences.js +1 -3
  67. package/lib/firefox/settings/firefoxPreferences.js +2 -4
  68. package/lib/firefox/settings/geckoProfilerDefaults.js +5 -9
  69. package/lib/firefox/webdriver/builder.js +66 -63
  70. package/lib/firefox/webdriver/firefox.js +43 -48
  71. package/lib/safari/webdriver/builder.js +4 -5
  72. package/lib/safari/webdriver/safari.js +4 -8
  73. package/lib/screenshot/defaults.js +1 -3
  74. package/lib/screenshot/index.js +24 -21
  75. package/lib/support/browserScript.js +65 -56
  76. package/lib/support/cli.js +123 -85
  77. package/lib/support/dns.js +6 -7
  78. package/lib/support/engineUtils.js +85 -38
  79. package/lib/support/errors.js +4 -13
  80. package/lib/support/fileUtil.js +81 -68
  81. package/lib/support/filters.js +15 -20
  82. package/lib/support/getViewPort.js +6 -7
  83. package/lib/support/har/index.js +208 -216
  84. package/lib/support/images/index.js +54 -26
  85. package/lib/support/logging.js +20 -17
  86. package/lib/support/pathToFolder.js +18 -23
  87. package/lib/support/preURL.js +5 -6
  88. package/lib/support/processes.js +4 -6
  89. package/lib/support/setResourceTimingBufferSize.js +2 -4
  90. package/lib/support/statistics.js +58 -56
  91. package/lib/support/stop.js +7 -8
  92. package/lib/support/storageManager.js +44 -44
  93. package/lib/support/tcpdump.js +22 -16
  94. package/lib/support/userTiming.js +7 -13
  95. package/lib/support/util.js +204 -224
  96. package/lib/support/xvfb.js +11 -13
  97. package/lib/video/defaults.js +6 -10
  98. package/lib/video/postprocessing/finetune/addTextToVideo.js +15 -15
  99. package/lib/video/postprocessing/finetune/convertFps.js +14 -8
  100. package/lib/video/postprocessing/finetune/getFont.js +7 -9
  101. package/lib/video/postprocessing/finetune/getTimingMetrics.js +19 -18
  102. package/lib/video/postprocessing/finetune/index.js +40 -36
  103. package/lib/video/postprocessing/finetune/removeOrange.js +10 -11
  104. package/lib/video/postprocessing/visualmetrics/extraMetrics.js +17 -13
  105. package/lib/video/postprocessing/visualmetrics/getVideoMetrics.js +12 -13
  106. package/lib/video/postprocessing/visualmetrics/visualMetrics.js +117 -128
  107. package/lib/video/screenRecording/android/recorder.js +12 -17
  108. package/lib/video/screenRecording/desktop/convert.js +13 -11
  109. package/lib/video/screenRecording/desktop/desktopRecorder.js +29 -24
  110. package/lib/video/screenRecording/desktop/ffmpegRecorder.js +60 -63
  111. package/lib/video/screenRecording/desktop/osx/getSPDisplaysDataType.js +4 -6
  112. package/lib/video/screenRecording/desktop/osx/getScreen.js +9 -10
  113. package/lib/video/screenRecording/firefox/firefoxWindowRecorder.js +54 -54
  114. package/lib/video/screenRecording/ios/convertToMp4.js +10 -11
  115. package/lib/video/screenRecording/ios/iosRecorder.js +23 -21
  116. package/lib/video/screenRecording/iosSimulator/convertToMp4.js +10 -11
  117. package/lib/video/screenRecording/iosSimulator/recorder.js +10 -9
  118. package/lib/video/screenRecording/recorder.js +8 -9
  119. package/lib/video/screenRecording/setOrangeBackground.js +5 -6
  120. package/lib/video/video.js +28 -34
  121. package/package.json +19 -17
@@ -1,26 +1,24 @@
1
- 'use strict';
2
-
3
- const isEmpty = require('lodash.isempty');
4
- const crypto = require('crypto');
5
- const log = require('intel').getLogger('browsertime');
6
- const urlParser = require('url');
1
+ import { parse } from 'node:url';
2
+ import { createHash } from 'node:crypto';
3
+ import isEmpty from 'lodash.isempty';
4
+ import intel from 'intel';
5
+ const log = intel.getLogger('browsertime');
7
6
 
8
7
  function toSafeKey(key) {
9
8
  // U+2013 : EN DASH – as used on https://en.wikipedia.org/wiki/2019–20_coronavirus_pandemic
10
- return key.replace(/[.~ /+|,:?&%–)(]|%7C/g, '-');
9
+ return key.replace(/[ %&()+,./:?|~–]|%7C/g, '-');
11
10
  }
12
11
 
13
- module.exports = function (url, options) {
12
+ export default function (url, options) {
14
13
  if (options.useSameDir) {
15
14
  return '';
16
15
  } else {
17
16
  const useHash = options.useHash;
18
- const parsedUrl = urlParser.parse(decodeURIComponent(url));
17
+ const parsedUrl = parse(decodeURIComponent(url));
19
18
 
20
19
  const pathSegments = [];
21
20
  const urlSegments = [];
22
- pathSegments.push('pages');
23
- pathSegments.push(parsedUrl.hostname.split('.').join('_'));
21
+ pathSegments.push('pages', parsedUrl.hostname.split('.').join('_'));
24
22
 
25
23
  if (options.urlMetaData && options.urlMetaData[url]) {
26
24
  pathSegments.push(options.urlMetaData[url]);
@@ -30,14 +28,14 @@ module.exports = function (url, options) {
30
28
  }
31
29
 
32
30
  if (useHash && !isEmpty(parsedUrl.hash)) {
33
- const md5 = crypto.createHash('md5'),
34
- hash = md5.update(parsedUrl.hash).digest('hex').substring(0, 8);
31
+ const md5 = createHash('md5'),
32
+ hash = md5.update(parsedUrl.hash).digest('hex').slice(0, 8);
35
33
  urlSegments.push('hash-' + hash);
36
34
  }
37
35
 
38
36
  if (!isEmpty(parsedUrl.search)) {
39
- const md5 = crypto.createHash('md5'),
40
- hash = md5.update(parsedUrl.search).digest('hex').substring(0, 8);
37
+ const md5 = createHash('md5'),
38
+ hash = md5.update(parsedUrl.search).digest('hex').slice(0, 8);
41
39
  urlSegments.push('query-' + hash);
42
40
  }
43
41
 
@@ -50,7 +48,7 @@ module.exports = function (url, options) {
50
48
  log.info(
51
49
  `The URL ${url} hit the 255 character limit used when stored on disk, you may want to give your URL an alias to make sure it will not collide with other URLs.`
52
50
  );
53
- pathSegments.push(folder.substr(0, 254));
51
+ pathSegments.push(folder.slice(0, 254));
54
52
  } else {
55
53
  pathSegments.push(folder);
56
54
  }
@@ -59,15 +57,12 @@ module.exports = function (url, options) {
59
57
 
60
58
  pathSegments.push('data');
61
59
 
62
- pathSegments.forEach(function (segment, index) {
60
+ for (const [index, segment] of pathSegments.entries()) {
63
61
  if (segment) {
64
- pathSegments[index] = segment.replace(
65
- /[^-a-z0-9_.\u0621-\u064A]/gi,
66
- '-'
67
- );
62
+ pathSegments[index] = segment.replace(/[^\w.\u0621-\u064A-]/gi, '-');
68
63
  }
69
- });
64
+ }
70
65
 
71
66
  return pathSegments.join('/').concat('/');
72
67
  }
73
- };
68
+ }
@@ -1,9 +1,8 @@
1
- 'use strict';
2
-
3
- const log = require('intel').getLogger('browsertime');
1
+ import intel from 'intel';
2
+ const log = intel.getLogger('browsertime');
4
3
  const delay = ms => new Promise(res => setTimeout(res, ms));
5
4
 
6
- module.exports = async function (browser, options) {
5
+ export default async function (browser, options) {
7
6
  log.info('Accessing preURL %s', options.preURL);
8
7
  await browser.loadAndWait(options.preURL);
9
8
  if (!options.preURLDisableWhiteBackground) {
@@ -13,5 +12,5 @@ module.exports = async function (browser, options) {
13
12
  );
14
13
  }
15
14
 
16
- return delay(options.preURLDelay ? options.preURLDelay : 1500);
17
- };
15
+ return delay(options.preURLDelay ?? 1500);
16
+ }
@@ -1,7 +1,5 @@
1
- 'use strict';
2
-
3
- const execa = require('execa');
4
- module.exports = async function () {
5
- const { stdout } = await execa.command('ps aux | wc -l', { shell: true });
1
+ import { execaCommand as command } from 'execa';
2
+ export default async function () {
3
+ const { stdout } = await command('ps aux | wc -l', { shell: true });
6
4
  return stdout;
7
- };
5
+ }
@@ -1,8 +1,6 @@
1
- 'use strict';
2
-
3
- module.exports = async function (startURL, driver, size) {
1
+ export default async function (startURL, driver, size) {
4
2
  await driver.get(startURL);
5
3
  await driver.executeScript(
6
4
  `window.performance.setResourceTimingBufferSize(${size});`
7
5
  );
8
- };
6
+ }
@@ -1,12 +1,8 @@
1
- 'use strict';
2
- /*
3
- * Utility functions for managing statistics of collected metrics and timings.
4
- */
5
-
6
- const get = require('lodash.get');
7
- const set = require('lodash.set');
8
- const Stats = require('fast-stats').Stats;
9
- const log = require('intel').getLogger('browsertime');
1
+ import get from 'lodash.get';
2
+ import set from 'lodash.set';
3
+ import { Stats } from 'fast-stats';
4
+ import intel from 'intel';
5
+ const log = intel.getLogger('browsertime');
10
6
 
11
7
  function validateType(value, type, message) {
12
8
  if (typeof value !== type) {
@@ -24,7 +20,17 @@ function percentileName(percentile) {
24
20
  }
25
21
  }
26
22
 
27
- class Statistics {
23
+ function isNumeric(n) {
24
+ return !Number.isNaN(Number.parseFloat(n)) && Number.isFinite(n);
25
+ }
26
+
27
+ function addNumber(target, key, value) {
28
+ let stats = get(target, key, new Stats());
29
+ stats.push(value);
30
+ set(target, key, stats);
31
+ }
32
+
33
+ export class Statistics {
28
34
  constructor() {
29
35
  this.data = {};
30
36
  }
@@ -32,7 +38,7 @@ class Statistics {
32
38
  add(key, value) {
33
39
  validateType(key, 'string', 'key (' + key + ') must be a string');
34
40
  validateType(value, 'number', 'value (' + value + ') must be a number');
35
- if (!isFinite(value)) {
41
+ if (!Number.isFinite(value)) {
36
42
  throw new RangeError("value can't be infinite");
37
43
  }
38
44
 
@@ -43,28 +49,18 @@ class Statistics {
43
49
  addAll(data) {
44
50
  let samples = Array.isArray(data) ? data : [data];
45
51
 
46
- samples.forEach(sample => {
47
- Object.keys(sample).forEach(key => {
52
+ for (const sample of samples) {
53
+ for (const key of Object.keys(sample)) {
48
54
  let value = sample[key];
49
55
  // TODO check type of value, to see if it should be included. Possibly via optional transform function
50
56
  this.add(key, value);
51
- });
52
- });
57
+ }
58
+ }
53
59
 
54
60
  return this;
55
61
  }
56
62
 
57
63
  addDeep(data, tranformFunction) {
58
- function isNumeric(n) {
59
- return !isNaN(parseFloat(n)) && isFinite(n);
60
- }
61
-
62
- function addNumber(target, key, value) {
63
- let stats = get(target, key, new Stats());
64
- stats.push(value);
65
- set(target, key, stats);
66
- }
67
-
68
64
  function addRecursive(target, keyPrefix, value) {
69
65
  if (tranformFunction && keyPrefix.length > 0) {
70
66
  value = tranformFunction(keyPrefix, value);
@@ -72,43 +68,48 @@ class Statistics {
72
68
  const valueType = typeof value;
73
69
 
74
70
  switch (valueType) {
75
- case 'number':
71
+ case 'number': {
76
72
  {
77
73
  addNumber(target, keyPrefix, value);
78
74
  }
79
75
  break;
76
+ }
80
77
 
81
- case 'object':
78
+ case 'object': {
82
79
  {
83
80
  if (value === null) {
84
81
  break;
85
82
  }
86
- Object.keys(value).forEach(key => {
87
- const path = keyPrefix.concat([key]);
83
+ for (const key of Object.keys(value)) {
84
+ const path = [...keyPrefix, key];
88
85
  addRecursive(target, path, value[key]);
89
- });
86
+ }
90
87
  }
91
88
  break;
89
+ }
92
90
 
93
- case 'string':
91
+ case 'string': {
94
92
  {
95
93
  if (isNumeric(value)) {
96
- addNumber(target, keyPrefix, parseFloat(value));
94
+ addNumber(target, keyPrefix, Number.parseFloat(value));
97
95
  }
98
96
  }
99
97
  break;
100
- case 'boolean':
98
+ }
99
+ case 'boolean': {
101
100
  {
102
101
  // skip
103
102
  }
104
103
  break;
104
+ }
105
105
 
106
- default:
106
+ default: {
107
107
  log.error(
108
108
  'Unhandled value type %s found when adding data for %s ',
109
109
  valueType,
110
110
  keyPrefix
111
111
  );
112
+ }
112
113
  }
113
114
  }
114
115
 
@@ -120,6 +121,7 @@ class Statistics {
120
121
  options = options || {};
121
122
  let percentiles = options.percentiles || [0, 10, 90, 99, 100];
122
123
 
124
+ // eslint-disable-next-line unicorn/no-array-reduce
123
125
  return Object.keys(this.data).reduce((results, key) => {
124
126
  let decimals = options.decimals || 0;
125
127
  let stats = get(this.data, [key]);
@@ -131,16 +133,16 @@ class Statistics {
131
133
  decimals = 4;
132
134
  }
133
135
  const node = {
134
- median: parseFloat(stats.median().toFixed(decimals)),
135
- mean: parseFloat(stats.amean().toFixed(decimals)),
136
- mdev: parseFloat(
136
+ median: Number.parseFloat(stats.median().toFixed(decimals)),
137
+ mean: Number.parseFloat(stats.amean().toFixed(decimals)),
138
+ mdev: Number.parseFloat(
137
139
  stats.stddev() / Math.sqrt(stats.length).toFixed(decimals)
138
140
  ) // "standard deviation of the mean"
139
141
  };
140
- percentiles.forEach(function (p) {
142
+ for (const p of percentiles) {
141
143
  let name = percentileName(p);
142
- node[name] = parseFloat(stats.percentile(p).toFixed(decimals));
143
- });
144
+ node[name] = Number.parseFloat(stats.percentile(p).toFixed(decimals));
145
+ }
144
146
  set(results, [key], node);
145
147
 
146
148
  return results;
@@ -165,19 +167,23 @@ class Statistics {
165
167
  decimals = 4;
166
168
  }
167
169
  const results = {
168
- median: parseFloat(stats.median().toFixed(decimals)),
169
- mean: parseFloat(stats.amean().toFixed(decimals)),
170
- mdev: parseFloat((stats.stddev() / Math.sqrt(stats.length)).toFixed(4)), // "standard deviation of the mean"
170
+ median: Number.parseFloat(stats.median().toFixed(decimals)),
171
+ mean: Number.parseFloat(stats.amean().toFixed(decimals)),
172
+ mdev: Number.parseFloat(
173
+ (stats.stddev() / Math.sqrt(stats.length)).toFixed(4)
174
+ ), // "standard deviation of the mean"
171
175
  rsd:
172
176
  stats.stddev() > 0
173
- ? parseFloat((100 * stats.stddev()) / stats.amean())
177
+ ? Number.parseFloat((100 * stats.stddev()) / stats.amean())
174
178
  : 0, // Relative standard deviation
175
- stddev: parseFloat(stats.stddev().toFixed(decimals))
179
+ stddev: Number.parseFloat(stats.stddev().toFixed(decimals))
176
180
  };
177
- percentiles.forEach(p => {
181
+ for (const p of percentiles) {
178
182
  let name = percentileName(p);
179
- results[name] = parseFloat(stats.percentile(p).toFixed(decimals));
180
- });
183
+ results[name] = Number.parseFloat(
184
+ stats.percentile(p).toFixed(decimals)
185
+ );
186
+ }
181
187
  return results;
182
188
  }
183
189
 
@@ -185,12 +191,12 @@ class Statistics {
185
191
  if (data instanceof Stats) {
186
192
  set(target, keyPrefix, summarize(data));
187
193
  } else if (typeof data === 'object') {
188
- Object.keys(data).forEach(key => {
189
- const path = keyPrefix.concat([key]);
194
+ for (const key of Object.keys(data)) {
195
+ const path = [...keyPrefix, key];
190
196
  summarizeRecursive(target, path, data[key]);
191
- });
197
+ }
192
198
  } else {
193
- throw new Error(
199
+ throw new TypeError(
194
200
  'Unhandled data type ' + typeof data + ' found when summarizing data'
195
201
  );
196
202
  }
@@ -201,7 +207,3 @@ class Statistics {
201
207
  return result;
202
208
  }
203
209
  }
204
-
205
- module.exports = {
206
- Statistics: Statistics
207
- };
@@ -1,12 +1,11 @@
1
- 'use strict';
1
+ import { execa } from 'execa';
2
+ import intel from 'intel';
3
+ const log = intel.getLogger('browsertime');
2
4
 
3
- const execa = require('execa');
4
- const log = require('intel').getLogger('browsertime');
5
-
6
- module.exports = async function (processName) {
7
- const scriptArgs = ['-9', processName];
5
+ export default async function (processName) {
6
+ const scriptArguments = ['-9', processName];
8
7
 
9
8
  log.debug('Kill all processes ' + processName);
10
9
 
11
- return execa('pkill', scriptArgs, { reject: false });
12
- };
10
+ return execa('pkill', scriptArguments, { reject: false });
11
+ }
@@ -1,33 +1,39 @@
1
- 'use strict';
2
-
3
- const log = require('intel').getLogger('browsertime');
4
- const fs = require('fs');
5
- const isEmpty = require('lodash.isempty');
6
- const path = require('path');
7
- const crypto = require('crypto');
8
- const zlib = require('zlib');
9
- const urlParser = require('url');
10
- const dayjs = require('dayjs');
11
- const { promisify } = require('util');
12
- const gunzip = promisify(zlib.gunzip);
13
- const writeFile = promisify(fs.writeFile);
14
- const readFile = promisify(fs.readFile);
15
- const gzip = promisify(zlib.gzip);
16
- const unlink = promisify(fs.unlink);
17
- const mkdir = promisify(fs.mkdir);
1
+ import { resolve as _resolve, join } from 'node:path';
2
+ import { createHash } from 'node:crypto';
3
+ import { gunzip as _gunzip, gzip as _gzip, createGzip } from 'node:zlib';
4
+ import { parse } from 'node:url';
5
+ import { promisify } from 'node:util';
6
+ import {
7
+ writeFile as _writeFile,
8
+ readFile as _readFile,
9
+ unlink as _unlink,
10
+ mkdir as _mkdir,
11
+ createReadStream,
12
+ createWriteStream
13
+ } from 'node:fs';
14
+ import isEmpty from 'lodash.isempty';
15
+ import intel from 'intel';
16
+ import dayjs from 'dayjs';
17
+ const gunzip = promisify(_gunzip);
18
+ const writeFile = promisify(_writeFile);
19
+ const readFile = promisify(_readFile);
20
+ const gzip = promisify(_gzip);
21
+ const unlink = promisify(_unlink);
22
+ const mkdir = promisify(_mkdir);
23
+ const log = intel.getLogger('browsertime');
18
24
 
19
25
  const defaultDir = 'browsertime-results';
20
26
  let timestamp = dayjs().format().replace(/:/g, '');
21
27
 
22
28
  function pathNameFromUrl(url) {
23
- const parsedUrl = urlParser.parse(url),
29
+ const parsedUrl = parse(url),
24
30
  pathSegments = parsedUrl.pathname.split('/');
25
31
 
26
32
  pathSegments.unshift(parsedUrl.hostname);
27
33
 
28
34
  if (!isEmpty(parsedUrl.search)) {
29
- const md5 = crypto.createHash('md5'),
30
- hash = md5.update(parsedUrl.search).digest('hex').substring(0, 8);
35
+ const md5 = createHash('md5'),
36
+ hash = md5.update(parsedUrl.search).digest('hex').slice(0, 8);
31
37
  pathSegments.push('query-' + hash);
32
38
  }
33
39
 
@@ -45,11 +51,9 @@ async function streamToString(stream) {
45
51
 
46
52
  class StorageManager {
47
53
  constructor(url, { resultDir, prettyPrint = false } = {}) {
48
- if (resultDir) {
49
- this.baseDir = path.resolve(resultDir);
50
- } else {
51
- this.baseDir = path.resolve(defaultDir, pathNameFromUrl(url), timestamp);
52
- }
54
+ this.baseDir = resultDir
55
+ ? _resolve(resultDir)
56
+ : _resolve(defaultDir, pathNameFromUrl(url), timestamp);
53
57
  this.jsonIndentation = prettyPrint ? 2 : 0;
54
58
  }
55
59
 
@@ -59,23 +63,21 @@ class StorageManager {
59
63
  }
60
64
 
61
65
  async createSubDataDir(...name) {
62
- const dir = path.join(this.baseDir, ...name);
66
+ const dir = join(this.baseDir, ...name);
63
67
  await mkdir(dir, { recursive: true });
64
68
  return dir;
65
69
  }
66
70
 
67
71
  async rm(filename) {
68
- return unlink(path.join(this.baseDir, filename));
72
+ return unlink(join(this.baseDir, filename));
69
73
  }
70
74
 
71
75
  async writeData(filename, data, subdir) {
72
76
  let dirPath;
73
- if (subdir) {
74
- dirPath = await this.createSubDataDir(subdir);
75
- } else {
76
- dirPath = await this.createDataDir();
77
- }
78
- const fullPath = path.join(dirPath, filename);
77
+ dirPath = await (subdir
78
+ ? this.createSubDataDir(subdir)
79
+ : this.createDataDir());
80
+ const fullPath = join(dirPath, filename);
79
81
  return writeFile(fullPath, data).then(() => {
80
82
  return fullPath;
81
83
  });
@@ -86,21 +88,19 @@ class StorageManager {
86
88
  const data = await gzip(Buffer.from(JSON.stringify(json)), { level: 1 });
87
89
  return this.writeData(`${filename}.gz`, data);
88
90
  } else {
89
- const data = JSON.stringify(json, null, this.jsonIndentation);
91
+ const data = JSON.stringify(json, undefined, this.jsonIndentation);
90
92
  return this.writeData(filename, data);
91
93
  }
92
94
  }
93
95
 
94
96
  async readData(filename, subdir) {
95
97
  let filepath;
96
- if (subdir) {
97
- filepath = path.join(this.baseDir, subdir, filename);
98
- } else {
99
- filepath = path.join(this.baseDir, filename);
100
- }
98
+ filepath = subdir
99
+ ? join(this.baseDir, subdir, filename)
100
+ : join(this.baseDir, filename);
101
101
 
102
102
  if (filename.endsWith('.gz')) {
103
- const readStream = fs.createReadStream(filepath);
103
+ const readStream = createReadStream(filepath);
104
104
  const text = await streamToString(readStream);
105
105
  const unzipped = await gunzip(text);
106
106
  return unzipped.toString();
@@ -111,9 +111,9 @@ class StorageManager {
111
111
 
112
112
  async gzip(inputFile, outputFile, removeInput) {
113
113
  const promise = new Promise(function (resolve, reject) {
114
- const gzip = zlib.createGzip();
115
- const input = fs.createReadStream(inputFile);
116
- const out = fs.createWriteStream(outputFile);
114
+ const gzip = createGzip();
115
+ const input = createReadStream(inputFile);
116
+ const out = createWriteStream(outputFile);
117
117
  out.on('finish', function () {
118
118
  if (removeInput) {
119
119
  unlink(inputFile).then(() => resolve());
@@ -135,4 +135,4 @@ class StorageManager {
135
135
  }
136
136
  }
137
137
 
138
- module.exports = StorageManager;
138
+ export default StorageManager;
@@ -1,41 +1,47 @@
1
- 'use strict';
2
- const execa = require('execa');
3
- const path = require('path');
4
- const pathToFolder = require('./pathToFolder');
5
- const fileUtil = require('./fileUtil');
1
+ import { join } from 'node:path';
2
+ import { execa } from 'execa';
3
+ import pathToFolder from './pathToFolder.js';
4
+ import { rename } from './fileUtil.js';
6
5
 
7
- class TCPDump {
6
+ export default class TCPDump {
8
7
  constructor(directory, options) {
9
8
  this.baseDir = directory;
10
9
  this.options = options;
11
10
  }
12
11
  async start(iteration) {
13
- const captureFile = path.join(this.baseDir, iteration + '.pcap');
14
- const params = ['tcpdump', '-i', 'any', '-s', '0', '-p', '-w', captureFile];
12
+ const captureFile = join(this.baseDir, iteration + '.pcap');
13
+ const parameters = [
14
+ 'tcpdump',
15
+ '-i',
16
+ 'any',
17
+ '-s',
18
+ '0',
19
+ '-p',
20
+ '-w',
21
+ captureFile
22
+ ];
15
23
  if (this.options.tcpdumpPacketBuffered) {
16
- params.push('-U');
24
+ parameters.push('-U');
17
25
  }
18
26
  if (this.options.tcpDumpParams) {
19
27
  const extras = Array.isArray(this.options.tcpDumpParams)
20
28
  ? this.options.tcpDumpParams
21
29
  : [this.options.tcpDumpParams];
22
- params.push(...extras);
30
+ parameters.push(...extras);
23
31
  }
24
- this.tcpdumpProcess = execa('sudo', params);
32
+ this.tcpdumpProcess = execa('sudo', parameters);
25
33
  }
26
34
  async stop() {
27
35
  return execa('sudo', ['pkill', '-9', 'tcpdump'], { reject: false });
28
36
  }
29
37
 
30
38
  async mv(url, iteration) {
31
- const oldLocation = path.join(this.baseDir, iteration + '.pcap');
32
- const newLocation = path.join(
39
+ const oldLocation = join(this.baseDir, iteration + '.pcap');
40
+ const newLocation = join(
33
41
  this.baseDir,
34
42
  pathToFolder(url, this.options),
35
43
  iteration + '.pcap'
36
44
  );
37
- return fileUtil.rename(oldLocation, newLocation);
45
+ return rename(oldLocation, newLocation);
38
46
  }
39
47
  }
40
-
41
- module.exports = TCPDump;
@@ -1,13 +1,7 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- filterWhitelisted(userTimings, whitelistRegex) {
5
- const allowed = new RegExp(whitelistRegex);
6
- userTimings.marks = userTimings.marks.filter(mark =>
7
- allowed.test(mark.name)
8
- );
9
- userTimings.measures = userTimings.measures.filter(measure =>
10
- allowed.test(measure.name)
11
- );
12
- }
13
- };
1
+ export function filterWhitelisted(userTimings, whitelistRegex) {
2
+ const allowed = new RegExp(whitelistRegex);
3
+ userTimings.marks = userTimings.marks.filter(mark => allowed.test(mark.name));
4
+ userTimings.measures = userTimings.measures.filter(measure =>
5
+ allowed.test(measure.name)
6
+ );
7
+ }