@jsenv/core 24.4.4 → 24.5.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 (37) hide show
  1. package/dist/browser_runtime/asset-manifest.json +1 -1
  2. package/dist/browser_runtime/{browser_runtime-75fe4f45.js → browser_runtime-c7288751.js} +7 -5
  3. package/dist/browser_runtime/{browser_runtime-75fe4f45.js.map → browser_runtime-c7288751.js.map} +3 -3
  4. package/dist/build_manifest.js +5 -5
  5. package/dist/compile_proxy/asset-manifest.json +1 -2
  6. package/dist/compile_proxy/{compile_proxy-58947390.html → compile_proxy-1dfca609.html} +259 -221
  7. package/dist/redirector/asset-manifest.json +1 -2
  8. package/dist/redirector/{redirector-3c40c078.html → redirector-d1316407.html} +259 -221
  9. package/dist/toolbar/asset-manifest.json +1 -2
  10. package/dist/toolbar/{toolbar-37d80823.html → toolbar-201c4093.html} +266 -223
  11. package/dist/toolbar/{toolbar.main-53e1ab2b.js.map → toolbar.main-320b0544.js.map} +3 -3
  12. package/dist/toolbar_injector/asset-manifest.json +1 -1
  13. package/dist/toolbar_injector/{toolbar_injector-b162830d.js → toolbar_injector-84042210.js} +2 -2
  14. package/dist/toolbar_injector/{toolbar_injector-b162830d.js.map → toolbar_injector-84042210.js.map} +4 -4
  15. package/package.json +3 -2
  16. package/readme.md +32 -36
  17. package/src/buildProject.js +2 -0
  18. package/src/internal/building/buildUsingRollup.js +16 -28
  19. package/src/internal/building/{bundleWorker.js → js/babel_plugin_inline_worker_imports.js} +25 -61
  20. package/src/internal/building/js/parseJsRessource.js +12 -13
  21. package/src/internal/building/js/transform_worker.js +55 -0
  22. package/src/internal/building/resolve_import_url_helper.js +2 -1
  23. package/src/internal/building/ressource_builder.js +59 -15
  24. package/src/internal/building/{createJsenvRollupPlugin.js → rollup_plugin_jsenv.js} +80 -9
  25. package/src/internal/building/url_loader.js +0 -2
  26. package/src/internal/compiling/createCompiledFileService.js +3 -3
  27. package/src/internal/dev_server/toolbar/util/dom.js +5 -0
  28. package/src/internal/executing/coverage_utils/v8_coverage_from_directory.js +9 -1
  29. package/src/internal/executing/createSummaryLog.js +4 -4
  30. package/src/internal/executing/executeConcurrently.js +1 -0
  31. package/src/internal/executing/executePlan.js +24 -10
  32. package/src/internal/executing/executionLogs.js +1 -1
  33. package/src/internal/runtime/s.js +6 -4
  34. package/dist/compile_proxy/assets/s.js-6192a06c.map +0 -246
  35. package/dist/redirector/assets/s.js-6192a06c.map +0 -246
  36. package/dist/toolbar/assets/s.js-6192a06c.map +0 -246
  37. package/src/internal/building/buildServiceWorker.js +0 -75
@@ -1,73 +1,24 @@
1
- import { readFileSync } from "fs"
2
1
  import {
3
2
  resolveUrl,
4
- urlToFileSystemPath,
5
3
  fileSystemPathToUrl,
4
+ urlToFileSystemPath,
6
5
  } from "@jsenv/filesystem"
7
- import { createDetailedMessage } from "@jsenv/logger"
8
- import { require } from "@jsenv/core/src/internal/require.js"
9
-
10
- export const bundleWorker = ({ workerScriptUrl, workerScriptSourceMap }) => {
11
- const { code, map } = transformWorkerScript(workerScriptUrl, {
12
- workerScriptSourceMap,
13
- })
14
- return { code, map }
15
- }
16
6
 
17
- const transformWorkerScript = (
18
- scriptUrl,
19
- { workerScriptSourceMap, importerUrl },
7
+ export const babelPluginInlineWorkerImports = (
8
+ babel,
9
+ { readImportedScript },
20
10
  ) => {
21
- const scriptPath = urlToFileSystemPath(scriptUrl)
22
- let scriptContent
23
- try {
24
- scriptContent = String(readFileSync(scriptPath))
25
- } catch (e) {
26
- if (e.code === "ENOENT") {
27
- if (importerUrl) {
28
- throw new Error(
29
- createDetailedMessage(`no file found for an import in a worker.`, {
30
- ["worker url"]: importerUrl,
31
- ["imported url"]: scriptUrl,
32
- }),
33
- )
34
- }
35
- throw new Error(`no worker file at ${scriptUrl}`)
36
- }
37
- throw e
38
- }
39
-
40
- const { transformSync } = require("@babel/core")
41
- const { code, map } = transformSync(scriptContent, {
42
- filename: scriptPath,
43
- configFile: false,
44
- babelrc: false, // trust only these options, do not read any babelrc config file
45
- ast: false,
46
- inputSourceMap: workerScriptSourceMap,
47
- sourceMaps: true,
48
- // sourceFileName: scriptPath,
49
- plugins: [[babelPluginInlineImportScripts, {}]],
50
- })
51
- return { code, map }
52
- }
11
+ const { types } = babel
53
12
 
54
- const babelPluginInlineImportScripts = (api) => {
55
- const { types, parse } = api
56
13
  return {
57
- name: "transform-inline-import-scripts",
14
+ name: "transform-inline-worker-imports",
58
15
 
59
16
  visitor: {
60
- CallExpression: (
61
- path,
62
- {
63
- file: {
64
- opts: { filename },
65
- },
66
- },
67
- ) => {
17
+ CallExpression: (path, opts) => {
68
18
  const calleePath = path.get("callee")
69
19
 
70
20
  const replaceImportScriptsWithFileContents = () => {
21
+ const filename = opts.filename
71
22
  const fileUrl = fileSystemPathToUrl(filename)
72
23
 
73
24
  let previousArgType = ""
@@ -97,11 +48,24 @@ const babelPluginInlineImportScripts = (api) => {
97
48
 
98
49
  if (previousArgType === "local") {
99
50
  const nodes = importedUrls.reduce((previous, importedUrl) => {
100
- const importedScriptResult = transformWorkerScript(importedUrl, {
101
- importerUrl: fileUrl,
51
+ const importedScriptCode = readImportedScript(importedUrl)
52
+ const { ast } = babel.transformSync(importedScriptCode, {
53
+ filename: urlToFileSystemPath(importedUrl),
54
+ configFile: false,
55
+ babelrc: false, // trust only these options, do not read any babelrc config file
56
+ ast: true,
57
+ sourceMaps: true,
58
+ // sourceFileName: scriptPath,
59
+ plugins: [
60
+ [
61
+ babelPluginInlineWorkerImports,
62
+ {
63
+ readImportedScript,
64
+ },
65
+ ],
66
+ ],
102
67
  })
103
- const importedSourceAst = parse(importedScriptResult.code)
104
- return [...previous, ...importedSourceAst.program.body]
68
+ return [...previous, ...ast.program.body]
105
69
  }, [])
106
70
 
107
71
  calleePath.parentPath.replaceWithMultiple(nodes)
@@ -4,7 +4,7 @@ import {
4
4
  getJavaScriptSourceMappingUrl,
5
5
  setJavaScriptSourceMappingUrl,
6
6
  } from "@jsenv/core/src/internal/sourceMappingURLUtils.js"
7
- import { bundleWorker } from "@jsenv/core/src/internal/building/bundleWorker.js"
7
+ import { transformWorker } from "./transform_worker.js"
8
8
 
9
9
  export const parseJsRessource = async (
10
10
  jsRessource,
@@ -47,19 +47,18 @@ export const parseJsRessource = async (
47
47
  map = JSON.parse(String(sourcemapRessource.bufferBeforeBuild))
48
48
  }
49
49
 
50
- // in case this js asset is a worker, bundle it so that:
51
- // importScripts are inlined which is good for:
52
- // - not breaking things (otherwise we would have to copy imported files in the build directory)
53
- // - perf (one less http request)
54
- const mightBeAWorkerScript = !jsRessource.isInline
55
- if (mightBeAWorkerScript) {
56
- const workerScriptUrl = asOriginalUrl(jsUrl)
57
- const workerBundle = await bundleWorker({
58
- workerScriptUrl,
59
- workerScriptSourceMap: map,
50
+ // in case this js asset is a worker, we transform it so that
51
+ // importScripts() calls are inlined
52
+ // We could also parse each importScripts call and decide to inline
53
+ // or not. For now inlining/concatenation is forced
54
+ if (jsRessource.isWorker || jsRessource.isServiceWorker) {
55
+ const transformResult = await transformWorker({
56
+ url: asOriginalUrl(jsUrl),
57
+ code: String(jsRessource.bufferBeforeBuild),
58
+ map,
60
59
  })
61
- code = workerBundle.code
62
- map = workerBundle.map
60
+ code = transformResult.code
61
+ map = transformResult.map
63
62
  } else {
64
63
  code = jsString
65
64
  }
@@ -0,0 +1,55 @@
1
+ // we could inline a worker by doing
2
+ // var blob = new Blob(code, { type: 'text/javascript' })
3
+ // window.URL.createObjectURL(blob)
4
+
5
+ import { readFileSync } from "fs"
6
+ import { urlToFileSystemPath } from "@jsenv/filesystem"
7
+ import { createDetailedMessage } from "@jsenv/logger"
8
+
9
+ import { babelPluginInlineWorkerImports } from "./babel_plugin_inline_worker_imports.js"
10
+
11
+ export const transformWorker = async ({ url, code, map }) => {
12
+ const { transformSync } = await import("@babel/core")
13
+
14
+ const transformResult = transformSync(code, {
15
+ filename: urlToFileSystemPath(url),
16
+ configFile: false,
17
+ babelrc: false, // trust only these options, do not read any babelrc config file
18
+ ast: false,
19
+ inputSourceMap: map,
20
+ sourceMaps: true,
21
+ // sourceFileName: scriptPath,
22
+ plugins: [
23
+ [
24
+ babelPluginInlineWorkerImports,
25
+ {
26
+ readImportedScript: readWorkerFile,
27
+ },
28
+ ],
29
+ ],
30
+ })
31
+ code = transformResult.code
32
+ map = transformResult.map
33
+ return { code, map }
34
+ }
35
+
36
+ export const readWorkerFile = (url, importerUrl) => {
37
+ const filePath = urlToFileSystemPath(url)
38
+ try {
39
+ const code = String(readFileSync(filePath))
40
+ return code
41
+ } catch (e) {
42
+ if (e.code === "ENOENT") {
43
+ if (importerUrl) {
44
+ throw new Error(
45
+ createDetailedMessage(`no file found for an import in a worker.`, {
46
+ ["worker url"]: importerUrl,
47
+ ["imported url"]: url,
48
+ }),
49
+ )
50
+ }
51
+ throw new Error(`no worker file at ${url}`)
52
+ }
53
+ throw e
54
+ }
55
+ }
@@ -4,7 +4,8 @@ window.__resolveImportUrl__ = (url, baseUrl) => {
4
4
 
5
5
  if (importmapNode) {
6
6
  const importmap = JSON.parse(importmapNode.textContent)
7
- return new URL(importmap.imports[url], baseUrl)
7
+ const specifier = importmap.imports[url] || url
8
+ return new URL(specifier, baseUrl)
8
9
  }
9
10
 
10
11
  return new URL(url, baseUrl)
@@ -5,7 +5,7 @@ import {
5
5
  urlToParentUrl,
6
6
  urlToFilename,
7
7
  } from "@jsenv/filesystem"
8
- import { createLogger } from "@jsenv/logger"
8
+ import { createLogger, loggerToLevels } from "@jsenv/logger"
9
9
 
10
10
  import { setJavaScriptSourceMappingUrl } from "@jsenv/core/src/internal/sourceMappingURLUtils.js"
11
11
  import { racePromises } from "../promise_race.js"
@@ -143,6 +143,9 @@ export const createRessourceBuilder = (
143
143
  contentType,
144
144
  bufferBeforeBuild,
145
145
  })
146
+ if (!reference) {
147
+ return null
148
+ }
146
149
  await reference.ressource.getReadyPromise()
147
150
  return reference
148
151
  }
@@ -229,10 +232,18 @@ export const createRessourceBuilder = (
229
232
 
230
233
  let ressourceUrl
231
234
  let isExternal = false
235
+ let isWorker = false
236
+ let isServiceWorker = false
232
237
  if (typeof ressourceUrlResolution === "object") {
233
- if (ressourceUrlResolution.external) {
238
+ if (ressourceUrlResolution.isExternal) {
234
239
  isExternal = true
235
240
  }
241
+ if (ressourceUrlResolution.isWorker) {
242
+ isWorker = true
243
+ }
244
+ if (ressourceUrlResolution.isServiceWorker) {
245
+ isServiceWorker = true
246
+ }
236
247
  ressourceUrl = ressourceUrlResolution.url
237
248
  } else {
238
249
  ressourceUrl = ressourceUrlResolution
@@ -292,6 +303,8 @@ export const createRessourceBuilder = (
292
303
  isExternal,
293
304
  isInline,
294
305
  isPlaceholder,
306
+ isWorker,
307
+ isServiceWorker,
295
308
  fileNamePattern,
296
309
  urlVersioningDisabled,
297
310
  })
@@ -330,14 +343,16 @@ export const createRessourceBuilder = (
330
343
  } else {
331
344
  ressource.references.push(reference)
332
345
  const effects = ressource.applyReferenceEffects(reference, { isJsModule })
333
- logger.debug(
334
- formatFoundReference({
335
- reference,
336
- referenceEffects: effects,
337
- showReferenceSourceLocation,
338
- shortenUrl,
339
- }),
340
- )
346
+ if (loggerToLevels(logger).debug) {
347
+ logger.debug(
348
+ formatFoundReference({
349
+ reference,
350
+ referenceEffects: effects,
351
+ showReferenceSourceLocation,
352
+ shortenUrl,
353
+ }),
354
+ )
355
+ }
341
356
  }
342
357
 
343
358
  return reference
@@ -356,9 +371,11 @@ export const createRessourceBuilder = (
356
371
  isExternal = false,
357
372
  isInline = false,
358
373
  isPlaceholder = false,
374
+ isWorker = false,
375
+ isServiceWorker = false,
359
376
 
360
377
  fileNamePattern,
361
- urlVersioningDisabled = false,
378
+ urlVersioningDisabled = isServiceWorker,
362
379
  }) => {
363
380
  const ressource = {
364
381
  contentType,
@@ -373,6 +390,8 @@ export const createRessourceBuilder = (
373
390
  isInline,
374
391
  isExternal,
375
392
  isPlaceholder,
393
+ isWorker,
394
+ isServiceWorker,
376
395
 
377
396
  urlVersioningDisabled,
378
397
  fileNamePattern,
@@ -424,12 +443,13 @@ export const createRessourceBuilder = (
424
443
 
425
444
  const response = await urlFetcher.fetchUrl(ressource.url, {
426
445
  contentTypeExpected: ressource.firstStrongReference.contentTypeExpected,
427
- urlTrace: () =>
428
- createRessourceTrace({
446
+ urlTrace: () => {
447
+ return createRessourceTrace({
429
448
  ressource,
430
449
  createUrlSiteFromReference,
431
450
  findRessourceByUrl,
432
- }),
451
+ })
452
+ },
433
453
  })
434
454
  if (response.url !== ressource.url) {
435
455
  const urlBeforeRedirection = ressource.url
@@ -875,7 +895,7 @@ export const createRessourceBuilder = (
875
895
  ? String(referenceSource)
876
896
  : ""
877
897
 
878
- return {
898
+ const urlSite = {
879
899
  type:
880
900
  referenceRessource && referenceRessource.isJsModule
881
901
  ? "import"
@@ -885,6 +905,30 @@ export const createRessourceBuilder = (
885
905
  column: referenceColumn,
886
906
  source: referenceSourceAsString,
887
907
  }
908
+
909
+ if (!referenceRessource.isInline) {
910
+ return urlSite
911
+ }
912
+ const { firstStrongReference } = referenceRessource
913
+ if (!firstStrongReference) {
914
+ return urlSite
915
+ }
916
+ const htmlUrlSite = createUrlSiteFromReference(firstStrongReference)
917
+ // when the html node is injected there is no line in the source file to target
918
+ if (htmlUrlSite.line === undefined) {
919
+ return urlSite
920
+ }
921
+ const importerRessource = findRessourceByUrl(
922
+ firstStrongReference.referenceUrl,
923
+ )
924
+ if (!importerRessource || importerRessource.contentType !== "text/html") {
925
+ return urlSite
926
+ }
927
+ return {
928
+ ...htmlUrlSite,
929
+ line: htmlUrlSite.line + urlSite.line,
930
+ column: htmlUrlSite.column + urlSite.column,
931
+ }
888
932
  }
889
933
 
890
934
  const showReferenceSourceLocation = (reference) => {
@@ -65,6 +65,9 @@ export const createJsenvRollupPlugin = async ({
65
65
  externalImportSpecifiers,
66
66
  externalImportUrlPatterns,
67
67
  importPaths,
68
+ workers,
69
+ serviceWorkers,
70
+ serviceWorkerFinalizer,
68
71
 
69
72
  format,
70
73
  systemJsUrl,
@@ -98,6 +101,15 @@ export const createJsenvRollupPlugin = async ({
98
101
  lastErrorMessage = error.message
99
102
  }
100
103
 
104
+ const workerUrls = Object.keys(workers).map((key) =>
105
+ resolveUrl(key, projectDirectoryUrl),
106
+ )
107
+ const serviceWorkerUrls = Object.keys(serviceWorkers).map((key) =>
108
+ resolveUrl(key, projectDirectoryUrl),
109
+ )
110
+ const isWorkerUrl = (url) => workerUrls.includes(url)
111
+ const isServiceWorkerUrl = (url) => serviceWorkerUrls.includes(url)
112
+
101
113
  let ressourceBuilder
102
114
  let importResolver
103
115
  let rollupEmitFile = () => {}
@@ -194,7 +206,7 @@ export const createJsenvRollupPlugin = async ({
194
206
  compileDirectoryRelativeUrl,
195
207
  projectDirectoryUrl,
196
208
  )
197
- const compileDirectoryRemoteUrl = resolveDirectoryUrl(
209
+ const compileDirectoryServerUrl = resolveDirectoryUrl(
198
210
  compileDirectoryRelativeUrl,
199
211
  compileServerOrigin,
200
212
  )
@@ -371,7 +383,7 @@ export const createJsenvRollupPlugin = async ({
371
383
  )
372
384
  importMapUrl = applyUrlMappings(importMapUrl)
373
385
 
374
- if (!urlIsInsideOf(importMapUrl, compileDirectoryRemoteUrl)) {
386
+ if (!urlIsInsideOf(importMapUrl, compileDirectoryServerUrl)) {
375
387
  logger.warn(
376
388
  formatImportmapOutsideCompileDirectory({
377
389
  importMapInfo: importMapInfoFromHtml,
@@ -392,7 +404,7 @@ export const createJsenvRollupPlugin = async ({
392
404
  firstHtmlEntryPoint.entryProjectRelativeUrl
393
405
  const htmlCompiledUrl = resolveUrl(
394
406
  htmlProjectRelativeUrl,
395
- compileDirectoryRemoteUrl,
407
+ compileDirectoryServerUrl,
396
408
  )
397
409
  importMapUrl = htmlCompiledUrl
398
410
  fetchImportMap = () => {
@@ -404,7 +416,7 @@ export const createJsenvRollupPlugin = async ({
404
416
  } else if (importMapFileRelativeUrl) {
405
417
  importMapUrl = resolveUrl(
406
418
  importMapFileRelativeUrl,
407
- compileDirectoryRemoteUrl,
419
+ compileDirectoryServerUrl,
408
420
  )
409
421
  fetchImportMap = () => {
410
422
  return fetchImportMapFromUrl(
@@ -428,7 +440,7 @@ export const createJsenvRollupPlugin = async ({
428
440
  })
429
441
  const entryCompileServerUrl = resolveUrl(
430
442
  entryProjectRelativeUrl,
431
- compileDirectoryRemoteUrl,
443
+ compileDirectoryServerUrl,
432
444
  )
433
445
  return normalizeImportMap(defaultImportMap, entryCompileServerUrl)
434
446
  }
@@ -550,8 +562,26 @@ export const createJsenvRollupPlugin = async ({
550
562
  // and ignore them and console.info/debug about remote url (https, http, ...)
551
563
  const projectUrl = asProjectUrl(ressourceUrl)
552
564
  if (!projectUrl) {
553
- return { external: true, url: ressourceUrl }
565
+ return {
566
+ isExternal: true,
567
+ url: ressourceUrl,
568
+ }
569
+ }
570
+
571
+ const originalUrl = asOriginalUrl(projectUrl)
572
+ if (isWorkerUrl(originalUrl)) {
573
+ return {
574
+ isWorker: true,
575
+ url: ressourceUrl,
576
+ }
554
577
  }
578
+ if (isServiceWorkerUrl(originalUrl)) {
579
+ return {
580
+ isServiceWorker: true,
581
+ url: ressourceUrl,
582
+ }
583
+ }
584
+
555
585
  return ressourceUrl
556
586
  },
557
587
  emitChunk,
@@ -565,7 +595,7 @@ export const createJsenvRollupPlugin = async ({
565
595
  urlImporterMap[jsModuleUrl] = {
566
596
  url: resolveUrl(
567
597
  entryPointsPrepared[0].entryProjectRelativeUrl,
568
- compileDirectoryRemoteUrl,
598
+ compileDirectoryServerUrl,
569
599
  ),
570
600
  line: undefined,
571
601
  column: undefined,
@@ -615,7 +645,7 @@ export const createJsenvRollupPlugin = async ({
615
645
  const entryUrl =
616
646
  entryContentType === "text/html"
617
647
  ? resolveUrl(entryProjectRelativeUrl, compileServerOrigin)
618
- : resolveUrl(entryProjectRelativeUrl, compileDirectoryRemoteUrl)
648
+ : resolveUrl(entryProjectRelativeUrl, compileDirectoryServerUrl)
619
649
  await ressourceBuilder.createReferenceForEntryPoint({
620
650
  entryContentType,
621
651
  entryUrl,
@@ -640,7 +670,7 @@ export const createJsenvRollupPlugin = async ({
640
670
  if (specifier.endsWith(".html")) {
641
671
  importer = compileServerOrigin
642
672
  } else {
643
- importer = compileDirectoryRemoteUrl
673
+ importer = compileDirectoryServerUrl
644
674
  }
645
675
  } else {
646
676
  importer = asServerUrl(importer)
@@ -1284,6 +1314,18 @@ export const createJsenvRollupPlugin = async ({
1284
1314
  }
1285
1315
  })
1286
1316
 
1317
+ await finalizeServiceWorkers({
1318
+ serviceWorkers,
1319
+ serviceWorkerFinalizer,
1320
+ projectDirectoryUrl,
1321
+ buildDirectoryUrl,
1322
+ rollupBuild,
1323
+ buildMappings,
1324
+ buildManifest,
1325
+ lineBreakNormalization,
1326
+ minify,
1327
+ })
1328
+
1287
1329
  rollupBuild = sortObjectByPathnames(rollupBuild)
1288
1330
  buildManifest = sortObjectByPathnames(buildManifest)
1289
1331
  buildMappings = sortObjectByPathnames(buildMappings)
@@ -1505,3 +1547,32 @@ const acceptsJsonContentType = ({ node, format }) => {
1505
1547
  }
1506
1548
  return false
1507
1549
  }
1550
+
1551
+ const finalizeServiceWorkers = async ({
1552
+ serviceWorkers,
1553
+ serviceWorkerFinalizer,
1554
+ buildMappings,
1555
+ buildManifest,
1556
+ rollupBuild,
1557
+ lineBreakNormalization,
1558
+ }) => {
1559
+ await Promise.all(
1560
+ Object.keys(serviceWorkers).map(async (projectRelativeUrl) => {
1561
+ const buildRelativeUrl = buildMappings[projectRelativeUrl]
1562
+ if (!buildRelativeUrl) {
1563
+ throw new Error(
1564
+ `"${projectRelativeUrl}" service worker file missing in the build`,
1565
+ )
1566
+ }
1567
+ const buildFileContent = rollupBuild[buildRelativeUrl].source
1568
+ rollupBuild[buildRelativeUrl].source = serviceWorkerFinalizer(
1569
+ buildFileContent,
1570
+ {
1571
+ buildManifest,
1572
+ rollupBuild,
1573
+ lineBreakNormalization,
1574
+ },
1575
+ )
1576
+ }),
1577
+ )
1578
+ }
@@ -24,7 +24,6 @@ export const createUrlLoader = ({
24
24
  const loadUrl = async (rollupUrl, { signal, logger, ressourceBuilder }) => {
25
25
  let url = asServerUrl(rollupUrl)
26
26
  const { importType, urlWithoutImportType } = extractImportTypeFromUrl(url)
27
-
28
27
  // importing CSS from JS with import assertions
29
28
  if (importType === "css") {
30
29
  const importer = urlImporterMap[url]
@@ -79,7 +78,6 @@ export const createUrlLoader = ({
79
78
  map,
80
79
  }
81
80
  }
82
-
83
81
  // importing json from JS with import assertion
84
82
  if (importType === "json") {
85
83
  const importer = urlImporterMap[url]
@@ -56,9 +56,9 @@ export const createCompiledFileService = ({
56
56
  sourcemapMethod,
57
57
  sourcemapExcludeSources,
58
58
  }) => {
59
- const moduleFormats = {}
59
+ const compileIdModuleFormats = {}
60
60
  Object.keys(groupMap).forEach((groupName) => {
61
- moduleFormats[groupName] = canAvoidSystemJs({
61
+ compileIdModuleFormats[groupName] = canAvoidSystemJs({
62
62
  runtimeSupport: groupMap[groupName].minRuntimeVersions,
63
63
  })
64
64
  ? "esmodule"
@@ -187,7 +187,7 @@ export const createCompiledFileService = ({
187
187
  runtimeSupport,
188
188
  moduleOutFormat:
189
189
  moduleOutFormat === undefined
190
- ? moduleFormats[compileId]
190
+ ? compileIdModuleFormats[compileId]
191
191
  : moduleOutFormat,
192
192
  importMetaFormat,
193
193
  transformTopLevelAwait,
@@ -1,4 +1,9 @@
1
1
  export const updateIframeOverflowOnParentWindow = () => {
2
+ if (!window.parent) {
3
+ // can happen while parent iframe reloads
4
+ return
5
+ }
6
+
2
7
  const aTooltipIsOpened =
3
8
  document.querySelector("[data-tooltip-visible]") ||
4
9
  document.querySelector("[data-tooltip-auto-visible]")
@@ -35,9 +35,13 @@ export const visitNodeV8Directory = async ({
35
35
  await previous
36
36
 
37
37
  const dirEntryUrl = resolveUrl(dirEntry, coverageDirectoryUrl)
38
- const tryReadJsonFile = async () => {
38
+ const tryReadJsonFile = async (timeSpentTrying = 0) => {
39
39
  const fileContent = await readFile(dirEntryUrl, { as: "string" })
40
40
  if (fileContent === "") {
41
+ if (timeSpentTrying < 400) {
42
+ await new Promise((resolve) => setTimeout(resolve, 200))
43
+ return tryReadJsonFile(timeSpentTrying + 200)
44
+ }
41
45
  console.warn(`Coverage JSON file is empty at ${dirEntryUrl}`)
42
46
  return null
43
47
  }
@@ -46,6 +50,10 @@ export const visitNodeV8Directory = async ({
46
50
  const fileAsJson = JSON.parse(fileContent)
47
51
  return fileAsJson
48
52
  } catch (e) {
53
+ if (timeSpentTrying < 400) {
54
+ await new Promise((resolve) => setTimeout(resolve, 200))
55
+ return tryReadJsonFile(timeSpentTrying + 200)
56
+ }
49
57
  console.warn(
50
58
  createDetailedMessage(`Error while reading coverage file`, {
51
59
  "error stack": e.stack,
@@ -3,12 +3,12 @@ import { ANSI } from "@jsenv/log"
3
3
  import { msAsDuration } from "../logs/msAsDuration.js"
4
4
  import { EXECUTION_COLORS } from "./execution_colors.js"
5
5
 
6
- export const createSummaryLog = (summary) => `
7
- -------------- summary -----------------
6
+ export const createSummaryLog = (
7
+ summary,
8
+ ) => `-------------- summary -----------------
8
9
  ${createSummaryMessage(summary)}
9
10
  total duration: ${msAsDuration(summary.duration)}
10
- ----------------------------------------
11
- `
11
+ ----------------------------------------`
12
12
 
13
13
  const createSummaryMessage = ({
14
14
  executionCount,
@@ -133,6 +133,7 @@ export const executeConcurrently = async (
133
133
  }
134
134
  }
135
135
 
136
+ logger.info("")
136
137
  let executionLog = createLog({ newLine: "" })
137
138
  let abortedCount = 0
138
139
  let timedoutCount = 0
@@ -129,16 +129,30 @@ export const executePlan = async (
129
129
  })
130
130
 
131
131
  logger.debug(`Generate executions`)
132
- const executionSteps = await generateExecutionSteps(
133
- {
134
- ...plan,
135
- [compileServer.outDirectoryRelativeUrl]: null,
136
- },
137
- {
138
- signal: multipleExecutionsOperation.signal,
139
- projectDirectoryUrl,
140
- },
141
- )
132
+
133
+ let executionSteps
134
+ try {
135
+ executionSteps = await generateExecutionSteps(
136
+ {
137
+ ...plan,
138
+ [compileServer.outDirectoryRelativeUrl]: null,
139
+ },
140
+ {
141
+ signal: multipleExecutionsOperation.signal,
142
+ projectDirectoryUrl,
143
+ },
144
+ )
145
+ } catch (e) {
146
+ if (Abort.isAbortError(e)) {
147
+ return {
148
+ aborted: true,
149
+ planSummary: {},
150
+ planReport: {},
151
+ planCoverage: null,
152
+ }
153
+ }
154
+ throw e
155
+ }
142
156
  logger.debug(`${executionSteps.length} executions planned`)
143
157
 
144
158
  const result = await executeConcurrently(executionSteps, {