browsertime 16.17.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 +44 -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 +22 -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 +83 -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 +120 -87
  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,21 +1,19 @@
1
- 'use strict';
2
-
3
- const log = require('intel').getLogger('browsertime.firefox');
4
- const fs = require('fs');
5
- const { promisify } = require('util');
6
- const path = require('path');
7
- const harBuilder = require('../../support/har');
8
- const pathToFolder = require('../../support/pathToFolder');
9
- const rename = promisify(fs.rename);
10
- const get = require('lodash.get');
11
- const { isAndroidConfigured, Android } = require('../../android');
12
- const util = require('../../support/util.js');
13
- const fileUtil = require('../../support/fileUtil.js');
14
- const getHAR = require('../getHAR');
15
- const GeckoProfiler = require('../geckoProfiler');
16
- const MemoryReport = require('../memoryReport');
17
- const PerfStats = require('../perfStats.js');
18
-
1
+ import { rename as _rename } from 'node:fs';
2
+ import { promisify } from 'node:util';
3
+ import { join } from 'node:path';
4
+ import intel from 'intel';
5
+ import get from 'lodash.get';
6
+ import { getEmptyHAR, mergeHars } from '../../support/har/index.js';
7
+ import pathToFolder from '../../support/pathToFolder.js';
8
+ import { isAndroidConfigured, Android } from '../../android/index.js';
9
+ import { adjustVisualProgressTimestamps } from '../../support/util.js';
10
+ import { findFiles } from '../../support/fileUtil.js';
11
+ import getHAR from '../getHAR.js';
12
+ import GeckoProfiler from '../geckoProfiler.js';
13
+ import { MemoryReport } from '../memoryReport.js';
14
+ import { PerfStats } from '../perfStats.js';
15
+ const log = intel.getLogger('browsertime.firefox');
16
+ const rename = promisify(_rename);
19
17
  class Firefox {
20
18
  constructor(storageManager, options) {
21
19
  // Lets keep this and hope that we in the future will have HAR for FF again
@@ -41,7 +39,7 @@ class Firefox {
41
39
  this.android = new Android(this.options);
42
40
  }
43
41
 
44
- if (this.android && this.options.androidPower) {
42
+ if (isAndroidConfigured(this.options) && this.options.androidPower) {
45
43
  await this.android.startPowerTesting();
46
44
  }
47
45
  }
@@ -75,7 +73,7 @@ class Firefox {
75
73
  * Before each URL/test runs.
76
74
  */
77
75
  async beforeEachURL(runner) {
78
- if (this.android && this.options.androidPower) {
76
+ if (isAndroidConfigured(this.options) && this.options.androidPower) {
79
77
  await this.android.resetPowerUsage();
80
78
  }
81
79
 
@@ -105,7 +103,7 @@ class Firefox {
105
103
  async afterPageCompleteCheck(runner, index, url, alias) {
106
104
  const result = { url, alias };
107
105
 
108
- if (this.android && this.options.androidPower) {
106
+ if (isAndroidConfigured(this.options) && this.options.androidPower) {
109
107
  result.power = await this.android.measurePowerUsage(
110
108
  this.firefoxConfig.android.package
111
109
  );
@@ -178,15 +176,15 @@ class Firefox {
178
176
  }
179
177
 
180
178
  async postWork(index, results) {
181
- for (let i = 0; i < results.length; i++) {
179
+ for (const result of results) {
182
180
  if (this.firefoxConfig.collectMozLog) {
183
- const files = await fileUtil.findFiles(this.baseDir, 'moz_log.txt');
181
+ const files = await findFiles(this.baseDir, 'moz_log.txt');
184
182
  for (const file of files) {
185
183
  await rename(
186
184
  `${this.baseDir}/${file}`,
187
- path.join(
185
+ join(
188
186
  this.baseDir,
189
- pathToFolder(results[i].url, this.options),
187
+ pathToFolder(result.url, this.options),
190
188
  `${file}-${index}.txt`
191
189
  )
192
190
  );
@@ -195,7 +193,7 @@ class Firefox {
195
193
 
196
194
  if (this.firefoxConfig.geckoProfiler && this.options.visualMetrics) {
197
195
  const profileFilename = `geckoProfile-${index}.json.gz`;
198
- const profileSubdir = pathToFolder(results[i].url, this.options);
196
+ const profileSubdir = pathToFolder(result.url, this.options);
199
197
 
200
198
  try {
201
199
  const geckoProfile = JSON.parse(
@@ -209,9 +207,9 @@ class Firefox {
209
207
  // by adding the time to first frame, time to orange screen to the unix timestamp of
210
208
  // video recording start time
211
209
  const firstFrameStartTime =
212
- results[i].recordingStartTime +
213
- results[i].videoRecordingStart +
214
- results[i].timeToFirstFrame;
210
+ result.recordingStartTime +
211
+ result.videoRecordingStart +
212
+ result.timeToFirstFrame;
215
213
 
216
214
  for (let progress of [
217
215
  'VisualProgress',
@@ -219,26 +217,25 @@ class Firefox {
219
217
  'PerceptualSpeedIndexProgress'
220
218
  ]) {
221
219
  // You can configure to not use content and perceptual.
222
- if (results[i].visualMetrics[progress]) {
223
- results[i].visualMetrics[progress] =
224
- util.adjustVisualProgressTimestamps(
225
- results[i].visualMetrics[progress],
226
- geckoProfile.meta.startTime,
227
- firstFrameStartTime
228
- );
220
+ if (result.visualMetrics[progress]) {
221
+ result.visualMetrics[progress] = adjustVisualProgressTimestamps(
222
+ result.visualMetrics[progress],
223
+ geckoProfile.meta.startTime,
224
+ firstFrameStartTime
225
+ );
229
226
  }
230
227
  }
231
- geckoProfile.meta.visualMetrics = results[i].visualMetrics;
228
+ geckoProfile.meta.visualMetrics = result.visualMetrics;
232
229
 
233
230
  await this.storageManager.writeJson(
234
- path.join(profileSubdir, `geckoProfile-${index}.json`),
231
+ join(profileSubdir, `geckoProfile-${index}.json`),
235
232
  geckoProfile,
236
233
  true
237
234
  );
238
- } catch (e) {
235
+ } catch (error) {
239
236
  log.error(
240
237
  `Could not rewrite visual progress using startimes and add visual metrics to ${profileFilename}`,
241
- e
238
+ error
242
239
  );
243
240
  }
244
241
  }
@@ -252,24 +249,22 @@ class Firefox {
252
249
  if (this.skipHar) {
253
250
  return;
254
251
  }
255
- this.hars.push(harBuilder.getEmptyHAR(url, 'Firefox'));
252
+ this.hars.push(getEmptyHAR(url, 'Firefox'));
256
253
  }
257
254
 
258
255
  /**
259
256
  * Get the HAR file for all the runs.
260
257
  */
261
258
  async getHARs() {
262
- if (!this.skipHar && this.hars.length > 0) {
263
- return { har: harBuilder.mergeHars(this.hars) };
264
- } else {
265
- return {};
266
- }
259
+ return !this.skipHar && this.hars.length > 0
260
+ ? { har: mergeHars(this.hars) }
261
+ : {};
267
262
  }
268
263
  /**
269
264
  * Before the browser is stopped/closed.
270
265
  */
271
266
  async beforeBrowserStop() {
272
- if (this.android && this.options.androidPower) {
267
+ if (isAndroidConfigured(this.options) && this.options.androidPower) {
273
268
  await this.android.stopPowerTesting();
274
269
  }
275
270
  }
@@ -280,4 +275,4 @@ class Firefox {
280
275
  async afterBrowserStopped() {}
281
276
  }
282
277
 
283
- module.exports = Firefox;
278
+ export default Firefox;
@@ -1,7 +1,6 @@
1
- 'use strict';
2
- const s = require('selenium-webdriver/safari');
1
+ import { Options } from 'selenium-webdriver/safari.js';
3
2
 
4
- module.exports.configureBuilder = async function (builder, baseDir, options) {
3
+ export async function configureBuilder(builder, baseDir, options) {
5
4
  const safariOptions = options.safari || {};
6
5
  builder
7
6
  .getCapabilities()
@@ -43,8 +42,8 @@ module.exports.configureBuilder = async function (builder, baseDir, options) {
43
42
  }
44
43
 
45
44
  if (safariOptions.useTechnologyPreview) {
46
- let o = new s.Options();
45
+ let o = new Options();
47
46
  o = o.setTechnologyPreview(true);
48
47
  builder.setSafariOptions(o);
49
48
  }
50
- };
49
+ }
@@ -1,10 +1,8 @@
1
- 'use strict';
2
-
3
1
  // const log = require('intel').getLogger('browsertime.safari');
4
- const execa = require('execa');
2
+ import { execaCommand as command } from 'execa';
5
3
  const delay = ms => new Promise(res => setTimeout(res, ms));
6
4
 
7
- class Safari {
5
+ export default class Safari {
8
6
  constructor(storageManager, options) {
9
7
  this.options = options;
10
8
  this.safariOptions = options.safari || {};
@@ -15,7 +13,7 @@ class Safari {
15
13
  */
16
14
  async beforeBrowserStart() {
17
15
  if (this.safariOptions.ios) {
18
- this.driverProcess = execa.command(
16
+ this.driverProcess = command(
19
17
  'safaridriver -p ' + this.options.safariDriverPort,
20
18
  {
21
19
  shell: true
@@ -86,7 +84,7 @@ class Safari {
86
84
 
87
85
  async afterBrowserStopped() {
88
86
  if (this.safariOptions.useSimulator) {
89
- await execa.command(
87
+ await command(
90
88
  'xcrun simctl terminate ' +
91
89
  this.safariOptions.deviceUDID +
92
90
  ' com.apple.mobilesafari',
@@ -101,5 +99,3 @@ class Safari {
101
99
  }
102
100
  }
103
101
  }
104
-
105
- module.exports = Safari;
@@ -1,6 +1,4 @@
1
- 'use strict';
2
-
3
- module.exports = {
1
+ export default {
4
2
  type: 'jpg',
5
3
  png: {
6
4
  compressionLevel: 6
@@ -1,18 +1,14 @@
1
- 'use strict';
2
- const merge = require('lodash.merge');
3
- const defaultConfig = require('./defaults');
4
- const path = require('path');
1
+ import { join } from 'node:path';
2
+ import merge from 'lodash.merge';
3
+ import intel from 'intel';
4
+ import defaultConfig from './defaults.js';
5
+ import {
6
+ savePngWithoutResize,
7
+ savePng,
8
+ saveJpg
9
+ } from '../support/images/index.js';
5
10
  const SCREENSHOT_DIR = 'screenshots';
6
- const images = require('../support/images');
7
- const log = require('intel').getLogger('browsertime.screenshot');
8
-
9
- let jimp;
10
- try {
11
- jimp = require('jimp');
12
- } catch (e) {
13
- jimp = null;
14
- }
15
-
11
+ const log = intel.getLogger('browsertime.screenshot');
16
12
  class ScreenshotManager {
17
13
  constructor(storageManager, options) {
18
14
  this.storageManager = storageManager;
@@ -22,18 +18,25 @@ class ScreenshotManager {
22
18
  }
23
19
 
24
20
  async save(name, data, url, index) {
21
+ let jimp;
22
+ try {
23
+ jimp = await import('jimp');
24
+ } catch {
25
+ jimp = undefined;
26
+ }
27
+
25
28
  if (!jimp) {
26
29
  if (this.config.type === 'jpg') {
27
30
  log.info(
28
31
  'Missing sharp dependency so you can only save images as png at viewport size'
29
32
  );
30
33
  }
31
- const pathAndName = await images.savePngWithoutResize(
34
+ const pathAndName = await savePngWithoutResize(
32
35
  name,
33
36
  data,
34
37
  url,
35
38
  this.storageManager,
36
- path.join(SCREENSHOT_DIR, `${index}`),
39
+ join(SCREENSHOT_DIR, `${index}`),
37
40
  this.options
38
41
  );
39
42
  this.savedScreenshots.push(
@@ -41,26 +44,26 @@ class ScreenshotManager {
41
44
  );
42
45
  }
43
46
  if (this.config.type === 'png') {
44
- const pathAndName = await images.savePng(
47
+ const pathAndName = await savePng(
45
48
  name,
46
49
  data,
47
50
  url,
48
51
  this.storageManager,
49
52
  this.config,
50
- path.join(SCREENSHOT_DIR, `${index}`),
53
+ join(SCREENSHOT_DIR, `${index}`),
51
54
  this.options
52
55
  );
53
56
  this.savedScreenshots.push(
54
57
  pathAndName.replace(this.storageManager.directory + '/', '')
55
58
  );
56
59
  } else {
57
- const pathAndName = await images.saveJpg(
60
+ const pathAndName = await saveJpg(
58
61
  name,
59
62
  data,
60
63
  url,
61
64
  this.storageManager,
62
65
  this.config,
63
- path.join(SCREENSHOT_DIR, `${index}`),
66
+ join(SCREENSHOT_DIR, `${index}`),
64
67
  this.options
65
68
  );
66
69
  this.savedScreenshots.push(
@@ -74,4 +77,4 @@ class ScreenshotManager {
74
77
  }
75
78
  }
76
79
 
77
- module.exports = ScreenshotManager;
80
+ export default ScreenshotManager;
@@ -1,14 +1,17 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const filters = require('./filters');
6
- const { promisify } = require('util');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { promisify } from 'node:util';
4
+ import { createRequire } from 'node:module';
5
+ import { fileURLToPath } from 'node:url';
6
+ import intel from 'intel';
7
+ import { onlyFiles, onlyWithExtension, onlyDirectories } from './filters.js';
8
+ const require = createRequire(import.meta.url);
7
9
  const readdir = promisify(fs.readdir);
8
10
  const readFile = promisify(fs.readFile);
9
11
  const stat = promisify(fs.stat);
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
13
  const rootFolder = path.resolve(__dirname, '..', '..', 'browserscripts');
11
- const log = require('intel').getLogger('browsertime');
14
+ const log = intel.getLogger('browsertime');
12
15
 
13
16
  function toFullPath(filename, root) {
14
17
  return path.join(root, filename);
@@ -20,12 +23,14 @@ function toFullPath(filename, root) {
20
23
  * @param {*} dirpath
21
24
  */
22
25
  async function scriptsFromDirectory(dirpath) {
23
- const dir = (await readdir(dirpath))
26
+ const dir = await readdir(dirpath);
27
+
28
+ const cleaned = dir
24
29
  .map(name => toFullPath(name, dirpath))
25
- .filter(await filters.onlyFiles)
26
- .filter(filters.onlyWithExtension('.js'));
30
+ .filter(await onlyFiles)
31
+ .filter(onlyWithExtension('.js'));
27
32
  const result = {};
28
- for (const filepath of dir) {
33
+ for (const filepath of cleaned) {
29
34
  const name = path.basename(filepath, '.js');
30
35
  const script = await readFile(filepath, 'utf8');
31
36
  result[name] = generateScriptObject(name, filepath, script);
@@ -34,12 +39,13 @@ async function scriptsFromDirectory(dirpath) {
34
39
  }
35
40
 
36
41
  async function getScriptsForCategories(categories) {
37
- const dirs = (await readdir(rootFolder))
42
+ const directories = await readdir(rootFolder);
43
+ const cleaned = directories
38
44
  .filter(name => categories.find(n => n === name))
39
45
  .map(name => toFullPath(name, rootFolder))
40
- .filter(await filters.onlyDirectories);
46
+ .filter(await onlyDirectories);
41
47
  const result = {};
42
- for (const dir of dirs) {
48
+ for (const dir of cleaned) {
43
49
  const name = path.basename(dir);
44
50
  const scripts = await scriptsFromDirectory(dir);
45
51
  result[name] = scripts;
@@ -77,13 +83,13 @@ function generateScriptObject(name, path, contents) {
77
83
  name: name,
78
84
  requires: scriptAndMetadataObject.requires,
79
85
  function: scriptAndMetadataObject.function,
80
- content: null,
86
+ content: undefined,
81
87
  isAsync:
82
88
  Object.getPrototypeOf(scriptAndMetadataObject.function) ===
83
89
  Object.getPrototypeOf(async function () {})
84
90
  };
85
91
  }
86
- } catch (error) {
92
+ } catch {
87
93
  // Use this as a signal to fall back to an old-style script, but don't
88
94
  // perform any action
89
95
  }
@@ -93,7 +99,7 @@ function generateScriptObject(name, path, contents) {
93
99
  return {
94
100
  name: name,
95
101
  content: contents,
96
- function: null,
102
+ function: undefined,
97
103
  requires: {}
98
104
  };
99
105
  }
@@ -117,12 +123,13 @@ function generateScriptObject(name, path, contents) {
117
123
  */
118
124
  async function findAndParseScripts(root, category) {
119
125
  async function scriptsFromDirectory(dirpath) {
120
- const dir = (await readdir(dirpath))
126
+ const dir = await readdir(dirpath);
127
+ const cleaned = dir
121
128
  .map(name => toFullPath(name, dirpath))
122
- .filter(await filters.onlyFiles)
123
- .filter(filters.onlyWithExtension('.js'));
129
+ .filter(await onlyFiles)
130
+ .filter(onlyWithExtension('.js'));
124
131
  const result = {};
125
- for (const filepath of dir) {
132
+ for (const filepath of cleaned) {
126
133
  const name = path.basename(filepath, '.js');
127
134
  const script = await readFile(filepath, 'utf8');
128
135
 
@@ -142,44 +149,46 @@ async function findAndParseScripts(root, category) {
142
149
  }
143
150
 
144
151
  return stat(root).then(stats => {
145
- if (stats.isFile()) {
146
- return readFile(root, 'utf8').then(content => {
147
- const name = path.basename(root, '.js');
148
- let scripts = {};
149
-
150
- scripts[name] = generateScriptObject(name, root, content);
151
- let categories = {};
152
- categories[category] = scripts;
153
-
154
- return categories;
155
- });
156
- } else {
157
- return parseDirectory(root);
158
- }
152
+ return stats.isFile()
153
+ ? readFile(root, 'utf8').then(content => {
154
+ const name = path.basename(root, '.js');
155
+ let scripts = {};
156
+
157
+ scripts[name] = generateScriptObject(name, root, content);
158
+ let categories = {};
159
+ categories[category] = scripts;
160
+
161
+ return categories;
162
+ })
163
+ : parseDirectory(root);
159
164
  });
160
165
  }
161
166
 
162
- module.exports = {
163
- defaultScriptCategories: ['browser', 'pageinfo', 'timings'],
164
- // FIXME need to add async here, is that possible for properties?
165
- get allScriptCategories() {
166
- return readdir(rootFolder).then(files => {
167
- files = files.map(fileName => path.join(rootFolder, fileName));
168
- const p = [];
169
- for (const file of files) {
170
- p.push(filters.onlyDirectories(file));
171
- }
172
- return Promise.all(p).then(isDirs => {
173
- const onlyDirs = [];
174
- for (let i = 0; i < isDirs.length; i++) {
175
- if (isDirs[i]) {
176
- onlyDirs.push(files[i]);
177
- }
167
+ const defaultScriptCategories = ['browser', 'pageinfo', 'timings'];
168
+
169
+ // FIXME need to add async here, is that possible for properties?
170
+ async function allScriptCategories() {
171
+ return readdir(rootFolder).then(files => {
172
+ files = files.map(fileName => path.join(rootFolder, fileName));
173
+ const p = [];
174
+ for (const file of files) {
175
+ p.push(onlyDirectories(file));
176
+ }
177
+ return Promise.all(p).then(isDirectories => {
178
+ const onlyDirectories = [];
179
+ for (const [index, isDirectory] of isDirectories.entries()) {
180
+ if (isDirectory) {
181
+ onlyDirectories.push(files[index]);
178
182
  }
179
- return onlyDirs.map(dirName => path.basename(dirName));
180
- });
183
+ }
184
+ return onlyDirectories.map(dirName => path.basename(dirName));
181
185
  });
182
- },
183
- getScriptsForCategories: getScriptsForCategories,
184
- findAndParseScripts: findAndParseScripts
186
+ });
187
+ }
188
+
189
+ export {
190
+ defaultScriptCategories,
191
+ allScriptCategories,
192
+ getScriptsForCategories,
193
+ findAndParseScripts
185
194
  };