@jsenv/core 23.1.3 → 23.2.2

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 (82) hide show
  1. package/dist/jsenv_browser_system.js +36 -99
  2. package/dist/jsenv_browser_system.js.map +12 -21
  3. package/dist/jsenv_compile_proxy.js +18 -82
  4. package/dist/jsenv_compile_proxy.js.map +11 -21
  5. package/dist/jsenv_exploring_index.js +127 -274
  6. package/dist/jsenv_exploring_index.js.map +76 -90
  7. package/dist/jsenv_exploring_redirector.js +21 -89
  8. package/dist/jsenv_exploring_redirector.js.map +13 -25
  9. package/dist/jsenv_toolbar.js +81 -149
  10. package/dist/jsenv_toolbar.js.map +50 -61
  11. package/dist/jsenv_toolbar_injector.js +185 -231
  12. package/dist/jsenv_toolbar_injector.js.map +30 -42
  13. package/package.json +8 -9
  14. package/src/abort/abortable.js +172 -0
  15. package/src/abort/callback_list.js +64 -0
  16. package/src/abort/callback_race.js +34 -0
  17. package/src/abort/cleaner.js +22 -0
  18. package/src/abort/main.js +32 -0
  19. package/src/abort/process_teardown_events.js +59 -0
  20. package/src/buildProject.js +132 -123
  21. package/src/execute.js +108 -107
  22. package/src/executeTestPlan.js +107 -125
  23. package/src/importUsingChildProcess.js +2 -1
  24. package/src/internal/browser-launcher/executeHtmlFile.js +33 -12
  25. package/src/internal/browser-utils/fetch-browser.js +4 -29
  26. package/src/internal/browser-utils/fetchUsingXHR.js +5 -7
  27. package/src/internal/building/buildUsingRollup.js +60 -24
  28. package/src/internal/building/createJsenvRollupPlugin.js +13 -31
  29. package/src/internal/building/ressource_builder.js +3 -6
  30. package/src/internal/building/sourcemap_loader.js +4 -5
  31. package/src/internal/building/url_fetcher.js +2 -5
  32. package/src/internal/building/url_loader.js +3 -6
  33. package/src/internal/compiling/compileFile.js +1 -2
  34. package/src/internal/compiling/createCompiledFileService.js +8 -9
  35. package/src/internal/compiling/startCompileServer.js +74 -135
  36. package/src/internal/executing/coverage/generateCoverageJsonFile.js +20 -3
  37. package/src/internal/executing/coverage/relativeUrlToEmptyCoverage.js +19 -30
  38. package/src/internal/executing/coverage/reportToCoverage.js +44 -24
  39. package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +2 -15
  40. package/src/internal/executing/createSummaryLog.js +50 -37
  41. package/src/internal/executing/executeConcurrently.js +89 -47
  42. package/src/internal/executing/executePlan.js +33 -7
  43. package/src/internal/executing/executionLogs.js +25 -28
  44. package/src/internal/executing/execution_colors.js +15 -0
  45. package/src/internal/executing/generateExecutionSteps.js +3 -2
  46. package/src/internal/executing/launchAndExecute.js +217 -261
  47. package/src/internal/exploring/fetchExploringJson.js +3 -4
  48. package/src/internal/fetchUrl.js +6 -2
  49. package/src/internal/logs/log_style.js +16 -28
  50. package/src/internal/logs/msAsDuration.js +1 -1
  51. package/src/internal/node-launcher/createChildProcessOptions.js +4 -5
  52. package/src/internal/node-launcher/createControllableNodeProcess.js +117 -229
  53. package/src/internal/node-launcher/kill_process_tree.js +76 -0
  54. package/src/internal/node-launcher/nodeControllableFile.mjs +16 -10
  55. package/src/internal/{promise_track_race.js → promise_race.js} +2 -2
  56. package/src/internal/runtime/s.js +25 -24
  57. package/src/internal/toolbar/toolbar.html +157 -61
  58. package/src/internal/toolbar/toolbar.injector.js +8 -0
  59. package/src/internal/toolbar/util/animation.js +3 -7
  60. package/src/internal/toolbar/util/fetching.js +1 -30
  61. package/src/jsenvServiceWorkerFinalizer.js +1 -2
  62. package/src/launchBrowser.js +131 -127
  63. package/src/launchNode.js +29 -17
  64. package/src/playwright_browser_versions.js +3 -3
  65. package/src/requireUsingChildProcess.js +2 -1
  66. package/src/signal/signal.js +65 -0
  67. package/src/startExploring.js +70 -72
  68. package/src/internal/executeJsenvAsyncFunction.js +0 -34
  69. package/src/internal/toolbar/animation/toolbar-movie-icon.svg +0 -15
  70. package/src/internal/toolbar/compilation/flask.svg +0 -7
  71. package/src/internal/toolbar/compilation/info.svg +0 -9
  72. package/src/internal/toolbar/compilation/loupe.svg +0 -11
  73. package/src/internal/toolbar/compilation/toolbar_compilation.svg +0 -11
  74. package/src/internal/toolbar/eventsource/toolbar-power-icon.svg +0 -10
  75. package/src/internal/toolbar/eventsource/toolbar-power-off-icon.svg +0 -10
  76. package/src/internal/toolbar/responsive/toolbar-dots-icon.svg +0 -10
  77. package/src/internal/toolbar/settings/toolbar-settings-icon.svg +0 -9
  78. package/src/internal/toolbar/theme/toolbar-palette-icon.svg +0 -10
  79. package/src/internal/toolbar/toolbar-cross-icon.svg +0 -10
  80. package/src/internal/toolbar/toolbar-loading-icon.svg +0 -102
  81. package/src/internal/toolbar/toolbar-notif-icon.svg +0 -9
  82. package/src/internal/trackRessources.js +0 -23
@@ -1,10 +1,4 @@
1
- /* eslint-disable import/max-dependencies */
2
1
  import { readFileSync } from "node:fs"
3
- import {
4
- createCancellationToken,
5
- createCancellationSource,
6
- composeCancellationToken,
7
- } from "@jsenv/cancellation"
8
2
  import {
9
3
  jsenvAccessControlAllowedHeaders,
10
4
  startServer,
@@ -12,6 +6,9 @@ import {
12
6
  createSSERoom,
13
7
  composeServicesWithTiming,
14
8
  urlToContentType,
9
+ pluginServerTiming,
10
+ pluginRequestWaitingCheck,
11
+ pluginCORS,
15
12
  } from "@jsenv/server"
16
13
  import { createLogger, createDetailedMessage } from "@jsenv/logger"
17
14
  import {
@@ -22,12 +19,12 @@ import {
22
19
  readFile,
23
20
  writeFile,
24
21
  ensureEmptyDirectory,
25
- registerFileLifecycle,
26
22
  registerDirectoryLifecycle,
27
23
  urlIsInsideOf,
28
24
  urlToBasename,
29
25
  } from "@jsenv/filesystem"
30
26
 
27
+ import { Abortable } from "@jsenv/core/src/abort/main.js"
31
28
  import { isBrowserPartOfSupportedRuntimes } from "@jsenv/core/src/internal/generateGroupMap/runtime_support.js"
32
29
  import { loadBabelPluginMapFromFile } from "./load_babel_plugin_map_from_file.js"
33
30
  import { extractSyntaxBabelPluginMap } from "./babel_plugins.js"
@@ -48,7 +45,7 @@ import { urlIsCompilationAsset } from "./compile-directory/compile-asset.js"
48
45
  import { createTransformHtmlSourceFileService } from "./html_source_file_service.js"
49
46
 
50
47
  export const startCompileServer = async ({
51
- cancellationToken = createCancellationToken(),
48
+ signal = new AbortController().signal,
52
49
  compileServerLogLevel,
53
50
 
54
51
  projectDirectoryUrl,
@@ -89,7 +86,7 @@ export const startCompileServer = async ({
89
86
  compileServerIp = "0.0.0.0",
90
87
  compileServerPort = 0,
91
88
  keepProcessAlive = false,
92
- stopOnPackageVersionChange = false,
89
+ onStop = () => {},
93
90
 
94
91
  // remaining options
95
92
  runtimeSupport,
@@ -218,15 +215,12 @@ export const startCompileServer = async ({
218
215
  ...babelPluginMap,
219
216
  }
220
217
 
221
- const serverStopCancellationSource = createCancellationSource()
218
+ const compileServerOperation = Abortable.fromSignal(signal)
222
219
 
223
220
  let projectFileRequestedCallback = () => {}
224
221
  if (livereloadSSE) {
225
222
  const sseSetup = setupServerSentEventsForLivereload({
226
- cancellationToken: composeCancellationToken(
227
- cancellationToken,
228
- serverStopCancellationSource.token,
229
- ),
223
+ compileServerOperation,
230
224
  projectDirectoryUrl,
231
225
  jsenvDirectoryRelativeUrl,
232
226
  outDirectoryRelativeUrl,
@@ -236,7 +230,7 @@ export const startCompileServer = async ({
236
230
 
237
231
  projectFileRequestedCallback = sseSetup.projectFileRequestedCallback
238
232
  const serveSSEForLivereload = createSSEForLivereloadService({
239
- cancellationToken,
233
+ compileServerOperation,
240
234
  outDirectoryRelativeUrl,
241
235
  trackMainAndDependencies: sseSetup.trackMainAndDependencies,
242
236
  })
@@ -283,31 +277,6 @@ export const startCompileServer = async ({
283
277
  })
284
278
  }
285
279
 
286
- const sourceFileService = composeServicesWithTiming({
287
- ...(transformHtmlSourceFiles
288
- ? {
289
- "service:transform html source file":
290
- createTransformHtmlSourceFileService({
291
- logger,
292
- projectDirectoryUrl,
293
- inlineImportMapIntoHTML,
294
- jsenvScriptInjection,
295
- jsenvToolbarInjection,
296
- }),
297
- }
298
- : {}),
299
- "service:source file": createSourceFileService({
300
- logger,
301
- projectDirectoryUrl,
302
- projectFileRequestedCallback,
303
- projectFileEtagEnabled,
304
- transformHtmlSourceFiles,
305
- inlineImportMapIntoHTML,
306
- jsenvScriptInjection,
307
- jsenvToolbarInjection,
308
- }),
309
- })
310
-
311
280
  const jsenvServices = {
312
281
  "service:compilation asset": createCompilationAssetFileService({
313
282
  projectDirectoryUrl,
@@ -327,8 +296,7 @@ export const startCompileServer = async ({
327
296
  projectDirectoryUrl,
328
297
  }),
329
298
  "service:compiled file": createCompiledFileService({
330
- sourceFileService,
331
- cancellationToken,
299
+ compileServerOperation,
332
300
  logger,
333
301
 
334
302
  projectDirectoryUrl,
@@ -352,10 +320,38 @@ export const startCompileServer = async ({
352
320
  sourcemapExcludeSources,
353
321
  compileCacheStrategy,
354
322
  }),
323
+ ...(transformHtmlSourceFiles
324
+ ? {
325
+ "service:transform html source file":
326
+ createTransformHtmlSourceFileService({
327
+ logger,
328
+ projectDirectoryUrl,
329
+ inlineImportMapIntoHTML,
330
+ jsenvScriptInjection,
331
+ jsenvToolbarInjection,
332
+ }),
333
+ }
334
+ : {}),
335
+ "service:source file": createSourceFileService({
336
+ logger,
337
+ projectDirectoryUrl,
338
+ projectFileRequestedCallback,
339
+ projectFileEtagEnabled,
340
+ transformHtmlSourceFiles,
341
+ inlineImportMapIntoHTML,
342
+ jsenvScriptInjection,
343
+ jsenvToolbarInjection,
344
+ }),
355
345
  }
356
346
 
357
347
  const compileServer = await startServer({
358
- cancellationToken,
348
+ signal: compileServerOperation.signal,
349
+ stopOnExit: false,
350
+ stopOnSIGINT: false,
351
+ stopOnInternalError: false,
352
+ sendServerInternalErrorDetails: true,
353
+ keepProcessAlive,
354
+
359
355
  logLevel: compileServerLogLevel,
360
356
 
361
357
  protocol: compileServerProtocol,
@@ -364,44 +360,32 @@ export const startCompileServer = async ({
364
360
  serverCertificatePrivateKey: compileServerPrivateKey,
365
361
  ip: compileServerIp,
366
362
  port: compileServerPort,
367
- sendServerTiming: true,
368
- // nagle: false,
369
- requestWaitingMs: 60 * 1000,
370
- sendServerInternalErrorDetails: true,
363
+ plugins: {
364
+ ...pluginCORS({
365
+ accessControlAllowRequestOrigin: true,
366
+ accessControlAllowRequestMethod: true,
367
+ accessControlAllowRequestHeaders: true,
368
+ accessControlAllowedRequestHeaders: [
369
+ ...jsenvAccessControlAllowedHeaders,
370
+ "x-jsenv-execution-id",
371
+ ],
372
+ accessControlAllowCredentials: true,
373
+ }),
374
+ ...pluginServerTiming,
375
+ ...pluginRequestWaitingCheck({
376
+ requestWaitingMs: 60 * 1000,
377
+ }),
378
+ },
371
379
  requestToResponse: composeServicesWithTiming({
372
380
  ...customServices,
373
381
  ...jsenvServices,
374
382
  }),
375
- accessControlAllowRequestOrigin: true,
376
- accessControlAllowRequestMethod: true,
377
- accessControlAllowRequestHeaders: true,
378
- accessControlAllowedRequestHeaders: [
379
- ...jsenvAccessControlAllowedHeaders,
380
- "x-jsenv-execution-id",
381
- ],
382
- accessControlAllowCredentials: true,
383
- keepProcessAlive,
383
+ onStop: () => {
384
+ onStop()
385
+ compileServerOperation.cleaner.clean()
386
+ },
384
387
  })
385
388
 
386
- compileServer.stoppedPromise.then(serverStopCancellationSource.cancel)
387
-
388
- if (stopOnPackageVersionChange) {
389
- const stopListeningJsenvPackageVersionChange =
390
- listenJsenvPackageVersionChange({
391
- projectDirectoryUrl,
392
- jsenvDirectoryRelativeUrl,
393
- onJsenvPackageVersionChange: () => {
394
- compileServer.stop(STOP_REASON_PACKAGE_VERSION_CHANGED)
395
- },
396
- })
397
- compileServer.stoppedPromise.then(
398
- () => {
399
- stopListeningJsenvPackageVersionChange()
400
- },
401
- () => {},
402
- )
403
- }
404
-
405
389
  return {
406
390
  jsenvDirectoryRelativeUrl,
407
391
  outDirectoryRelativeUrl,
@@ -575,7 +559,7 @@ const compareValueJson = (left, right) => {
575
559
  *
576
560
  */
577
561
  const setupServerSentEventsForLivereload = ({
578
- cancellationToken,
562
+ compileServerOperation,
579
563
  projectDirectoryUrl,
580
564
  jsenvDirectoryRelativeUrl,
581
565
  outDirectoryRelativeUrl,
@@ -621,7 +605,7 @@ const setupServerSentEventsForLivereload = ({
621
605
  recursive: true,
622
606
  },
623
607
  )
624
- cancellationToken.register(unregisterDirectoryLifecyle)
608
+ compileServerOperation.cleaner.addCallback(unregisterDirectoryLifecyle)
625
609
 
626
610
  const getDependencySet = (mainRelativeUrl) => {
627
611
  if (trackerMap.has(mainRelativeUrl)) {
@@ -777,11 +761,14 @@ const setupServerSentEventsForLivereload = ({
777
761
  }
778
762
  }
779
763
 
780
- return { projectFileRequestedCallback, trackMainAndDependencies }
764
+ return {
765
+ projectFileRequestedCallback,
766
+ trackMainAndDependencies,
767
+ }
781
768
  }
782
769
 
783
770
  const createSSEForLivereloadService = ({
784
- cancellationToken,
771
+ compileServerOperation,
785
772
  outDirectoryRelativeUrl,
786
773
  trackMainAndDependencies,
787
774
  }) => {
@@ -815,17 +802,18 @@ const createSSEForLivereloadService = ({
815
802
  },
816
803
  })
817
804
 
818
- const cancelRegistration = cancellationToken.register(() => {
819
- cancelRegistration.unregister()
820
-
821
- sseRoom.close()
822
- stopTracking()
823
- })
805
+ const removeSSECleanupCallback = compileServerOperation.cleaner.addCallback(
806
+ () => {
807
+ removeSSECleanupCallback()
808
+ sseRoom.close()
809
+ stopTracking()
810
+ },
811
+ )
824
812
  cache.push({
825
813
  mainFileRelativeUrl,
826
814
  sseRoom,
827
815
  cleanup: () => {
828
- cancelRegistration.unregister()
816
+ removeSSECleanupCallback()
829
817
  sseRoom.close()
830
818
  stopTracking()
831
819
  },
@@ -1122,51 +1110,6 @@ const createCompileProxyService = ({ projectDirectoryUrl }) => {
1122
1110
  }
1123
1111
  }
1124
1112
 
1125
- const listenJsenvPackageVersionChange = ({
1126
- projectDirectoryUrl,
1127
- jsenvDirectoryRelativeUrl,
1128
- onJsenvPackageVersionChange = () => {},
1129
- }) => {
1130
- const jsenvCoreDirectoryUrl = resolveUrl(
1131
- jsenvDirectoryRelativeUrl,
1132
- projectDirectoryUrl,
1133
- )
1134
- const packageFileUrl = resolveUrl("./package.json", jsenvCoreDirectoryUrl)
1135
- const packageFilePath = urlToFileSystemPath(packageFileUrl)
1136
- let packageVersion
1137
-
1138
- try {
1139
- packageVersion = readPackage(packageFilePath).version
1140
- } catch (e) {
1141
- if (e.code === "ENOENT") return () => {}
1142
- }
1143
-
1144
- const checkPackageVersion = () => {
1145
- let packageObject
1146
- try {
1147
- packageObject = readPackage(packageFilePath)
1148
- } catch (e) {
1149
- // package json deleted ? not a problem
1150
- // let's wait for it to show back
1151
- if (e.code === "ENOENT") return
1152
- // package.json malformed ? not a problem
1153
- // let's wait for use to fix it or filesystem to finish writing the file
1154
- if (e.name === "SyntaxError") return
1155
- throw e
1156
- }
1157
-
1158
- if (packageVersion !== packageObject.version) {
1159
- onJsenvPackageVersionChange()
1160
- }
1161
- }
1162
-
1163
- return registerFileLifecycle(packageFilePath, {
1164
- added: checkPackageVersion,
1165
- updated: checkPackageVersion,
1166
- keepProcessAlive: false,
1167
- })
1168
- }
1169
-
1170
1113
  const readPackage = (packagePath) => {
1171
1114
  const buffer = readFileSync(packagePath)
1172
1115
  const string = String(buffer)
@@ -1174,10 +1117,6 @@ const readPackage = (packagePath) => {
1174
1117
  return packageObject
1175
1118
  }
1176
1119
 
1177
- export const STOP_REASON_PACKAGE_VERSION_CHANGED = {
1178
- toString: () => `package version changed`,
1179
- }
1180
-
1181
1120
  const __filenameReplacement = `import.meta.url.slice('file:///'.length)`
1182
1121
 
1183
1122
  const __dirnameReplacement = `import.meta.url.slice('file:///'.length).replace(/[\\\/\\\\][^\\\/\\\\]*$/, '')`
@@ -1,5 +1,22 @@
1
- import { writeFile } from "@jsenv/filesystem"
1
+ import { writeFile, urlToFileSystemPath } from "@jsenv/filesystem"
2
2
 
3
- export const generateCoverageJsonFile = async (coverage, coverageJsonFileUrl) => {
4
- await writeFile(coverageJsonFileUrl, JSON.stringify(coverage, null, " "))
3
+ import { byteAsFileSize } from "@jsenv/core/src/internal/logs/byteAsFileSize.js"
4
+
5
+ export const generateCoverageJsonFile = async ({
6
+ coverage,
7
+ coverageJsonFileUrl,
8
+ coverageJsonFileLog,
9
+ logger,
10
+ }) => {
11
+ const coverageAsText = JSON.stringify(coverage, null, " ")
12
+
13
+ if (coverageJsonFileLog) {
14
+ logger.info(
15
+ `-> ${urlToFileSystemPath(coverageJsonFileUrl)} (${byteAsFileSize(
16
+ Buffer.byteLength(coverageAsText),
17
+ )})`,
18
+ )
19
+ }
20
+
21
+ await writeFile(coverageJsonFileUrl, coverageAsText)
5
22
  }
@@ -1,52 +1,41 @@
1
- import { createOperation } from "@jsenv/cancellation"
2
1
  import { resolveUrl, urlToFileSystemPath, readFile } from "@jsenv/filesystem"
3
2
 
3
+ import { Abortable } from "@jsenv/core/src/abort/main.js"
4
4
  import {
5
5
  babelPluginsFromBabelPluginMap,
6
6
  getMinimalBabelPluginMap,
7
7
  } from "@jsenv/core/src/internal/compiling/babel_plugins.js"
8
-
9
8
  import { babelPluginInstrument } from "./babel_plugin_instrument.js"
10
9
  import { createEmptyCoverage } from "./createEmptyCoverage.js"
11
10
 
12
11
  export const relativeUrlToEmptyCoverage = async (
13
12
  relativeUrl,
14
- { cancellationToken, projectDirectoryUrl, babelPluginMap },
13
+ { multipleExecutionsOperation, projectDirectoryUrl, babelPluginMap },
15
14
  ) => {
16
15
  const { transformAsync } = await import("@babel/core")
17
16
 
18
17
  const fileUrl = resolveUrl(relativeUrl, projectDirectoryUrl)
19
- const source = await createOperation({
20
- cancellationToken,
21
- start: () => readFile(fileUrl),
22
- })
18
+ Abortable.throwIfAborted(multipleExecutionsOperation)
19
+ const source = await readFile(fileUrl)
23
20
 
24
21
  try {
25
- const { metadata } = await createOperation({
26
- cancellationToken,
27
- start: async () => {
28
- babelPluginMap = {
29
- ...getMinimalBabelPluginMap(),
30
- ...babelPluginMap,
31
- "transform-instrument": [
32
- babelPluginInstrument,
33
- { projectDirectoryUrl },
34
- ],
35
- }
22
+ babelPluginMap = {
23
+ ...getMinimalBabelPluginMap(),
24
+ ...babelPluginMap,
25
+ "transform-instrument": [babelPluginInstrument, { projectDirectoryUrl }],
26
+ }
36
27
 
37
- const { metadata } = await transformAsync(source, {
38
- filename: urlToFileSystemPath(fileUrl),
39
- filenameRelative: relativeUrl,
40
- configFile: false,
41
- babelrc: false,
42
- ast: true,
43
- parserOpts: {
44
- allowAwaitOutsideFunction: true,
45
- },
46
- plugins: babelPluginsFromBabelPluginMap(babelPluginMap),
47
- })
48
- return { metadata }
28
+ Abortable.throwIfAborted(multipleExecutionsOperation)
29
+ const { metadata } = await transformAsync(source, {
30
+ filename: urlToFileSystemPath(fileUrl),
31
+ filenameRelative: relativeUrl,
32
+ configFile: false,
33
+ babelrc: false,
34
+ ast: true,
35
+ parserOpts: {
36
+ allowAwaitOutsideFunction: true,
49
37
  },
38
+ plugins: babelPluginsFromBabelPluginMap(babelPluginMap),
50
39
  })
51
40
 
52
41
  const { coverage } = metadata
@@ -1,4 +1,5 @@
1
1
  import { collectFiles } from "@jsenv/filesystem"
2
+
2
3
  import { relativeUrlToEmptyCoverage } from "./relativeUrlToEmptyCoverage.js"
3
4
  import { istanbulCoverageFromCoverages } from "./istanbulCoverageFromCoverages.js"
4
5
  import { normalizeIstanbulCoverage } from "./normalizeIstanbulCoverage.js"
@@ -6,8 +7,8 @@ import { normalizeIstanbulCoverage } from "./normalizeIstanbulCoverage.js"
6
7
  export const reportToCoverage = async (
7
8
  report,
8
9
  {
10
+ multipleExecutionsOperation,
9
11
  logger,
10
- cancellationToken,
11
12
  projectDirectoryUrl,
12
13
  babelPluginMap,
13
14
  coverageConfig,
@@ -15,50 +16,66 @@ export const reportToCoverage = async (
15
16
  coverageV8MergeConflictIsExpected,
16
17
  },
17
18
  ) => {
18
- const istanbulCoverageFromExecution = await executionReportToCoverage(report, {
19
- logger,
20
- projectDirectoryUrl,
21
- coverageV8MergeConflictIsExpected,
22
- })
19
+ // here we should forward multipleExecutionsOperation.signal
20
+ // to allow aborting this too
21
+ const istanbulCoverageFromExecution = await executionReportToCoverage(
22
+ report,
23
+ {
24
+ logger,
25
+ projectDirectoryUrl,
26
+ coverageV8MergeConflictIsExpected,
27
+ },
28
+ )
23
29
 
24
30
  if (!coverageIncludeMissing) {
25
31
  return istanbulCoverageFromExecution
26
32
  }
27
33
 
28
34
  const relativeFileUrlToCoverArray = await listRelativeFileUrlToCover({
29
- cancellationToken,
35
+ multipleExecutionsOperation,
30
36
  projectDirectoryUrl,
31
37
  coverageConfig,
32
38
  })
33
39
 
34
- const relativeFileUrlMissingCoverageArray = relativeFileUrlToCoverArray.filter(
35
- (relativeFileUrlToCover) =>
40
+ const relativeFileUrlMissingCoverageArray =
41
+ relativeFileUrlToCoverArray.filter((relativeFileUrlToCover) =>
36
42
  Object.keys(istanbulCoverageFromExecution).every((key) => {
37
43
  return key !== `./${relativeFileUrlToCover}`
38
44
  }),
39
- )
45
+ )
40
46
 
41
47
  const istanbulCoverageFromMissedFiles = {}
48
+ // maybe we should prefer reduce over Promise.all here
49
+ // because it creates a LOT of things to do
42
50
  await Promise.all(
43
- relativeFileUrlMissingCoverageArray.map(async (relativeFileUrlMissingCoverage) => {
44
- const emptyCoverage = await relativeUrlToEmptyCoverage(relativeFileUrlMissingCoverage, {
45
- cancellationToken,
46
- projectDirectoryUrl,
47
- babelPluginMap,
48
- })
49
- istanbulCoverageFromMissedFiles[relativeFileUrlMissingCoverage] = emptyCoverage
50
- return emptyCoverage
51
- }),
51
+ relativeFileUrlMissingCoverageArray.map(
52
+ async (relativeFileUrlMissingCoverage) => {
53
+ const emptyCoverage = await relativeUrlToEmptyCoverage(
54
+ relativeFileUrlMissingCoverage,
55
+ {
56
+ multipleExecutionsOperation,
57
+ projectDirectoryUrl,
58
+ babelPluginMap,
59
+ },
60
+ )
61
+ istanbulCoverageFromMissedFiles[relativeFileUrlMissingCoverage] =
62
+ emptyCoverage
63
+ return emptyCoverage
64
+ },
65
+ ),
52
66
  )
53
67
 
54
68
  return {
55
69
  ...istanbulCoverageFromExecution, // already normalized
56
- ...normalizeIstanbulCoverage(istanbulCoverageFromMissedFiles, projectDirectoryUrl),
70
+ ...normalizeIstanbulCoverage(
71
+ istanbulCoverageFromMissedFiles,
72
+ projectDirectoryUrl,
73
+ ),
57
74
  }
58
75
  }
59
76
 
60
77
  const listRelativeFileUrlToCover = async ({
61
- cancellationToken,
78
+ multipleExecutionsOperation,
62
79
  projectDirectoryUrl,
63
80
  coverageConfig,
64
81
  }) => {
@@ -67,7 +84,7 @@ const listRelativeFileUrlToCover = async ({
67
84
  }
68
85
 
69
86
  const matchingFileResultArray = await collectFiles({
70
- cancellationToken,
87
+ signal: multipleExecutionsOperation.signal,
71
88
  directoryUrl: projectDirectoryUrl,
72
89
  structuredMetaMap: structuredMetaMapForCoverage,
73
90
  predicate: ({ cover }) => cover,
@@ -85,7 +102,8 @@ const executionReportToCoverage = async (
85
102
  Object.keys(report).forEach((file) => {
86
103
  const executionResultForFile = report[file]
87
104
  Object.keys(executionResultForFile).forEach((executionName) => {
88
- const executionResultForFileOnRuntime = executionResultForFile[executionName]
105
+ const executionResultForFileOnRuntime =
106
+ executionResultForFile[executionName]
89
107
 
90
108
  const { status, coverage } = executionResultForFileOnRuntime
91
109
  if (!coverage) {
@@ -108,7 +126,9 @@ const executionReportToCoverage = async (
108
126
  // that were suppose to be coverage but were not.
109
127
 
110
128
  if (status === "completed") {
111
- logger.warn(`No execution.coverage from execution named "${executionName}" of ${file}`)
129
+ logger.warn(
130
+ `No execution.coverage from execution named "${executionName}" of ${file}`,
131
+ )
112
132
  }
113
133
  return
114
134
  }
@@ -26,15 +26,11 @@ export const v8CoverageFromNodeV8Directory = async ({
26
26
  }
27
27
 
28
28
  const readV8CoverageReportsFromDirectory = async (coverageDirectory) => {
29
- const tryReadDirectory = async (timeSpentTrying = 0) => {
29
+ const tryReadDirectory = async () => {
30
30
  const dirContent = await readDirectory(coverageDirectory)
31
31
  if (dirContent.length > 0) {
32
32
  return dirContent
33
33
  }
34
- if (timeSpentTrying < 800) {
35
- await new Promise((resolve) => setTimeout(resolve, 100))
36
- return tryReadDirectory(timeSpentTrying + 100)
37
- }
38
34
  console.warn(`v8 coverage directory is empty at ${coverageDirectory}`)
39
35
  return dirContent
40
36
  }
@@ -45,20 +41,11 @@ const readV8CoverageReportsFromDirectory = async (coverageDirectory) => {
45
41
  await Promise.all(
46
42
  dirContent.map(async (dirEntry) => {
47
43
  const dirEntryUrl = resolveUrl(dirEntry, coverageDirectoryUrl)
48
- const tryReadJsonFile = async (timeSpentTrying = 0) => {
44
+ const tryReadJsonFile = async () => {
49
45
  try {
50
46
  const fileContent = await readFile(dirEntryUrl, { as: "json" })
51
47
  return fileContent
52
48
  } catch (e) {
53
- if (e.name === "SyntaxError") {
54
- // If there is a syntax error it's likely because Node.js
55
- // is not done writing the json file content
56
- // -> let's retry to read file after 100ms
57
- if (timeSpentTrying < 100) {
58
- await new Promise((resolve) => setTimeout(resolve, 100))
59
- return tryReadJsonFile(timeSpentTrying + 100)
60
- }
61
- }
62
49
  console.warn(
63
50
  createDetailedMessage(`Error while reading coverage file`, {
64
51
  "error stack": e.stack,