@jsenv/core 27.0.0-alpha.81 → 27.0.0-alpha.84

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 (81) hide show
  1. package/dist/babel_helpers/applyDecs/applyDecs.js +756 -0
  2. package/dist/babel_helpers/construct/construct.js +1 -1
  3. package/dist/babel_helpers/extends/extends.js +1 -1
  4. package/dist/babel_helpers/get/get.js +1 -1
  5. package/dist/babel_helpers/getPrototypeOf/getPrototypeOf.js +1 -1
  6. package/dist/babel_helpers/identity/identity.js +3 -0
  7. package/dist/babel_helpers/setPrototypeOf/setPrototypeOf.js +2 -2
  8. package/dist/js/event_source_client.js +206 -2
  9. package/dist/main.js +934 -90
  10. package/dist/s.js.map +2 -1
  11. package/package.json +9 -9
  12. package/src/build/build.js +5 -5
  13. package/src/build/build_urls_generator.js +1 -2
  14. package/src/build/inject_global_version_mappings.js +2 -2
  15. package/src/build/inject_service_worker_urls.js +2 -2
  16. package/src/build/resync_ressource_hints.js +1 -1
  17. package/src/build/start_build_server.js +33 -26
  18. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +1 -2
  19. package/src/dev/plugins/toolbar/client/util/fetching.js +1 -1
  20. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +1 -1
  21. package/src/dev/start_dev_server.js +38 -30
  22. package/src/execute/runtimes/browsers/from_playwright.js +5 -4
  23. package/src/execute/runtimes/node/node_process.js +2 -2
  24. package/src/helpers/command/command.js +73 -0
  25. package/src/helpers/event_source/event_source.js +197 -0
  26. package/src/helpers/event_source/sse_service.js +53 -0
  27. package/src/helpers/worker_reload.js +57 -0
  28. package/src/omega/compat/runtime_compat.js +2 -1
  29. package/src/omega/kitchen.js +2 -1
  30. package/src/omega/server/user_agent.js +2 -1
  31. package/src/omega/url_graph/sort_by_dependencies.js +27 -0
  32. package/src/omega/url_graph/url_info_transformations.js +24 -14
  33. package/src/plugins/autoreload/dev_sse/client/event_source_client.js +1 -1
  34. package/src/plugins/autoreload/dev_sse/client/reload.js +1 -1
  35. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +1 -1
  36. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +1 -1
  37. package/src/plugins/bundling/css/bundle_css.js +5 -4
  38. package/src/plugins/bundling/js_module/bundle_js_module.js +2 -2
  39. package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +2 -2
  40. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +1 -2
  41. package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +1 -1
  42. package/src/plugins/import_meta_hot/html_hot_dependencies.js +2 -2
  43. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +4 -3
  44. package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +2 -2
  45. package/src/plugins/importmap/jsenv_plugin_importmap.js +2 -3
  46. package/src/plugins/inject_globals/inject_globals.js +2 -2
  47. package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
  48. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +3 -3
  49. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +4 -4
  50. package/src/plugins/minification/css/minify_css.js +1 -1
  51. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +2 -4
  52. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +5 -5
  53. package/src/plugins/transpilation/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +1 -1
  54. package/src/plugins/transpilation/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +2 -3
  55. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
  56. package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +1 -2
  57. package/src/plugins/transpilation/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +1 -2
  58. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +1 -1
  59. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +1 -1
  60. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +2 -1
  61. package/src/plugins/url_analysis/css/css_urls.js +3 -3
  62. package/src/plugins/url_analysis/html/html_urls.js +2 -2
  63. package/src/plugins/url_analysis/js/js_urls.js +3 -2
  64. package/src/test/coverage/babel_plugin_instrument.js +82 -0
  65. package/src/test/coverage/coverage_reporter_html_directory.js +36 -0
  66. package/src/test/coverage/coverage_reporter_json_file.js +22 -0
  67. package/src/test/coverage/coverage_reporter_text_log.js +19 -0
  68. package/src/test/coverage/empty_coverage_factory.js +52 -0
  69. package/src/test/coverage/file_by_file_coverage.js +25 -0
  70. package/src/test/coverage/istanbul_coverage_composition.js +28 -0
  71. package/src/test/coverage/istanbul_coverage_map_from_coverage.js +16 -0
  72. package/src/test/coverage/list_files_not_covered.js +15 -0
  73. package/src/test/coverage/missing_coverage.js +41 -0
  74. package/src/test/coverage/report_to_coverage.js +196 -0
  75. package/src/test/coverage/v8_and_istanbul.js +37 -0
  76. package/src/test/coverage/v8_coverage_composition.js +24 -0
  77. package/src/test/coverage/v8_coverage_from_directory.js +87 -0
  78. package/src/test/coverage/v8_coverage_to_istanbul.js +99 -0
  79. package/src/test/execute_plan.js +2 -2
  80. package/src/test/execute_test_plan.js +3 -3
  81. package/dist/babel_helpers/readme.md +0 -8
@@ -1,10 +1,10 @@
1
+ import { createMagicSource } from "@jsenv/sourcemap"
1
2
  import {
2
3
  parseHtmlString,
3
4
  injectScriptAsEarlyAsPossible,
4
5
  createHtmlNode,
5
6
  stringifyHtmlAst,
6
- } from "@jsenv/utils/html_ast/html_ast.js"
7
- import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
7
+ } from "@jsenv/utils/src/html_ast/html_ast.js"
8
8
 
9
9
  export const injectGlobals = (urlInfo, globals) => {
10
10
  if (urlInfo.type === "html") {
@@ -1,5 +1,5 @@
1
1
  import { DATA_URL } from "@jsenv/urls"
2
- import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
2
+ import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js"
3
3
 
4
4
  export const jsenvPluginDataUrls = () => {
5
5
  return {
@@ -1,3 +1,4 @@
1
+ import { generateInlineContentUrl } from "@jsenv/urls"
1
2
  import {
2
3
  parseHtmlString,
3
4
  stringifyHtmlAst,
@@ -7,9 +8,8 @@ import {
7
8
  parseScriptNode,
8
9
  setHtmlNodeGeneratedText,
9
10
  getHtmlNodeAttributeByName,
10
- } from "@jsenv/utils/html_ast/html_ast.js"
11
- import { generateInlineContentUrl } from "@jsenv/urls"
12
- import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
11
+ } from "@jsenv/utils/src/html_ast/html_ast.js"
12
+ import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js"
13
13
 
14
14
  export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
15
15
  return {
@@ -1,8 +1,8 @@
1
- import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
2
- import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
3
- import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
4
- import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
5
1
  import { generateInlineContentUrl } from "@jsenv/urls"
2
+ import { createMagicSource } from "@jsenv/sourcemap"
3
+ import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js"
4
+ import { JS_QUOTES } from "@jsenv/utils/src/string/js_quotes.js"
5
+ import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js"
6
6
 
7
7
  export const jsenvPluginJsInlineContent = ({ allowEscapeForVersioning }) => {
8
8
  const parseAndTransformInlineContentCalls = async (urlInfo, context) => {
@@ -1,4 +1,4 @@
1
- import { minifyWithParcel } from "@jsenv/utils/css_ast/parcel_css.js"
1
+ import { minifyWithParcel } from "@jsenv/utils/src/css_ast/parcel_css.js"
2
2
 
3
3
  export const minifyCss = ({ cssUrlInfo, context }) => {
4
4
  const { code, map } = minifyWithParcel(cssUrlInfo, context)
@@ -13,11 +13,9 @@
13
13
 
14
14
  import { urlToFilename, injectQueryParams } from "@jsenv/urls"
15
15
  import { readFileSync } from "@jsenv/filesystem"
16
-
16
+ import { createMagicSource, composeTwoSourcemaps } from "@jsenv/sourcemap"
17
17
  import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
18
- import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
19
- import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
20
- import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_composition_v3.js"
18
+ import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js"
21
19
 
22
20
  import { requireBabelPlugin } from "../babel/require_babel_plugin.js"
23
21
  import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
@@ -1,3 +1,7 @@
1
+ import {
2
+ generateInlineContentUrl,
3
+ injectQueryParamsIntoSpecifier,
4
+ } from "@jsenv/urls"
1
5
  import {
2
6
  getHtmlNodeAttributeByName,
3
7
  getHtmlNodeTextNode,
@@ -10,11 +14,7 @@ import {
10
14
  setHtmlNodeGeneratedText,
11
15
  injectScriptAsEarlyAsPossible,
12
16
  createHtmlNode,
13
- } from "@jsenv/utils/html_ast/html_ast.js"
14
- import {
15
- generateInlineContentUrl,
16
- injectQueryParamsIntoSpecifier,
17
- } from "@jsenv/urls"
17
+ } from "@jsenv/utils/src/html_ast/html_ast.js"
18
18
 
19
19
  export const jsenvPluginAsJsClassicHtml = ({
20
20
  systemJsInjection,
@@ -1,6 +1,6 @@
1
1
  import { pathToFileURL } from "node:url"
2
2
 
3
- import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js"
3
+ import { injectImport } from "@jsenv/utils/src/js_ast/babel_utils.js"
4
4
 
5
5
  export const babelPluginGlobalThisAsJsenvImport = (
6
6
  babel,
@@ -1,10 +1,9 @@
1
1
  import { pathToFileURL } from "node:url"
2
-
3
- import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js"
2
+ import { injectImport } from "@jsenv/utils/src/js_ast/babel_utils.js"
4
3
  import {
5
4
  getBabelHelperFileUrl,
6
5
  babelHelperNameFromUrl,
7
- } from "@jsenv/babel-plugins/main.js"
6
+ } from "@jsenv/babel-plugins"
8
7
 
9
8
  // named import approach found here:
10
9
  // https://github.com/rollup/rollup-plugin-babel/blob/18e4232a450f320f44c651aa8c495f21c74d59ac/src/helperPlugin.js#L1
@@ -1,4 +1,4 @@
1
- import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
1
+ import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js"
2
2
 
3
3
  import { RUNTIME_COMPAT } from "@jsenv/core/src/omega/compat/runtime_compat.js"
4
4
  import { getBaseBabelPluginStructure } from "./helpers/babel_plugin_structure.js"
@@ -1,6 +1,5 @@
1
1
  import { pathToFileURL } from "node:url"
2
-
3
- import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js"
2
+ import { injectImport } from "@jsenv/utils/src/js_ast/babel_utils.js"
4
3
 
5
4
  export const babelPluginNewStylesheetAsJsenvImport = (
6
5
  babel,
@@ -1,6 +1,5 @@
1
1
  import { pathToFileURL } from "node:url"
2
-
3
- import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js"
2
+ import { injectImport } from "@jsenv/utils/src/js_ast/babel_utils.js"
4
3
 
5
4
  export const babelPluginRegeneratorRuntimeAsJsenvImport = (
6
5
  babel,
@@ -1,4 +1,4 @@
1
- import { transpileWithParcel } from "@jsenv/utils/css_ast/parcel_css.js"
1
+ import { transpileWithParcel } from "@jsenv/utils/src/css_ast/parcel_css.js"
2
2
 
3
3
  // https://github.com/parcel-bundler/parcel-css
4
4
  export const jsenvPluginCssParcel = () => {
@@ -12,7 +12,7 @@
12
12
 
13
13
  import { urlToFilename, injectQueryParams } from "@jsenv/urls"
14
14
 
15
- import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
15
+ import { JS_QUOTES } from "@jsenv/utils/src/string/js_quotes.js"
16
16
 
17
17
  export const jsenvPluginImportAssertions = () => {
18
18
  const updateReference = (reference, searchParam) => {
@@ -1,4 +1,5 @@
1
- import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
1
+ import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js"
2
+
2
3
  import { requireBabelPlugin } from "./babel/require_babel_plugin.js"
3
4
 
4
5
  export const jsenvPluginTopLevelAwait = () => {
@@ -2,9 +2,9 @@
2
2
  * https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/css/src/CSSTransformer.js
3
3
  */
4
4
 
5
- import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
6
- import { applyPostCss } from "@jsenv/utils/css_ast/apply_post_css.js"
7
- import { postCssPluginUrlVisitor } from "@jsenv/utils/css_ast/postcss_plugin_url_visitor.js"
5
+ import { createMagicSource } from "@jsenv/sourcemap"
6
+ import { applyPostCss } from "@jsenv/utils/src/css_ast/apply_post_css.js"
7
+ import { postCssPluginUrlVisitor } from "@jsenv/utils/src/css_ast/postcss_plugin_url_visitor.js"
8
8
 
9
9
  export const parseAndTransformCssUrls = async (urlInfo, context) => {
10
10
  const actions = []
@@ -4,8 +4,8 @@ import {
4
4
  getHtmlNodeAttributeByName,
5
5
  htmlNodePosition,
6
6
  visitHtmlAst,
7
- } from "@jsenv/utils/html_ast/html_ast.js"
8
- import { htmlAttributeSrcSet } from "@jsenv/utils/html_ast/html_attribute_src_set.js"
7
+ } from "@jsenv/utils/src/html_ast/html_ast.js"
8
+ import { htmlAttributeSrcSet } from "@jsenv/utils/src/html_ast/html_attribute_src_set.js"
9
9
 
10
10
  export const parseAndTransformHtmlUrls = async (urlInfo, context) => {
11
11
  const url = urlInfo.originalUrl
@@ -1,5 +1,6 @@
1
- import { parseJsUrls } from "@jsenv/utils/js_ast/parse_js_urls.js"
2
- import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
1
+ import { createMagicSource } from "@jsenv/sourcemap"
2
+ import { parseJsUrls } from "@jsenv/utils/src/js_ast/parse_js_urls.js"
3
+
3
4
  import { isWebWorkerUrlInfo } from "@jsenv/core/src/omega/web_workers.js"
4
5
 
5
6
  export const parseAndTransformJsUrls = async (urlInfo, context) => {
@@ -0,0 +1,82 @@
1
+ import { URL_META } from "@jsenv/url-meta"
2
+ import { fileSystemPathToUrl } from "@jsenv/urls"
3
+
4
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
5
+
6
+ // https://github.com/istanbuljs/babel-plugin-istanbul/blob/321740f7b25d803f881466ea819d870f7ed6a254/src/index.js
7
+
8
+ export const babelPluginInstrument = (
9
+ api,
10
+ {
11
+ rootDirectoryUrl,
12
+ useInlineSourceMaps = false,
13
+ coverageConfig = { "./**/*": true },
14
+ },
15
+ ) => {
16
+ const { programVisitor } = requireFromJsenv("istanbul-lib-instrument")
17
+
18
+ const { types } = api
19
+
20
+ const associations = URL_META.resolveAssociations(
21
+ { cover: coverageConfig },
22
+ rootDirectoryUrl,
23
+ )
24
+ const shouldInstrument = (url) => {
25
+ return URL_META.applyAssociations({ url, associations }).cover
26
+ }
27
+
28
+ return {
29
+ name: "transform-instrument",
30
+ visitor: {
31
+ Program: {
32
+ enter(path) {
33
+ const { file } = this
34
+ const { opts } = file
35
+ if (!opts.sourceFileName) {
36
+ console.warn(
37
+ `cannot instrument file when "sourceFileName" option is not set`,
38
+ )
39
+ return
40
+ }
41
+ const fileUrl = fileSystemPathToUrl(opts.sourceFileName)
42
+ if (!shouldInstrument(fileUrl)) {
43
+ return
44
+ }
45
+
46
+ this.__dv__ = null
47
+
48
+ let inputSourceMap
49
+
50
+ if (useInlineSourceMaps) {
51
+ // https://github.com/istanbuljs/babel-plugin-istanbul/commit/a9e15643d249a2985e4387e4308022053b2cd0ad#diff-1fdf421c05c1140f6d71444ea2b27638R65
52
+ inputSourceMap =
53
+ opts.inputSourceMap || file.inputMap
54
+ ? file.inputMap.sourcemap
55
+ : null
56
+ } else {
57
+ inputSourceMap = opts.inputSourceMap
58
+ }
59
+
60
+ this.__dv__ = programVisitor(
61
+ types,
62
+ opts.filenameRelative || opts.filename,
63
+ {
64
+ coverageVariable: "__coverage__",
65
+ inputSourceMap,
66
+ },
67
+ )
68
+ this.__dv__.enter(path)
69
+ },
70
+
71
+ exit(path) {
72
+ if (!this.__dv__) {
73
+ return
74
+ }
75
+ const object = this.__dv__.exit(path)
76
+ // object got two properties: fileCoverage and sourceMappingURL
77
+ this.file.metadata.coverage = object.fileCoverage
78
+ },
79
+ },
80
+ },
81
+ }
82
+ }
@@ -0,0 +1,36 @@
1
+ import { readFileSync } from "node:fs"
2
+ import { resolveUrl, urlToFileSystemPath } from "@jsenv/urls"
3
+
4
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
5
+ import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js"
6
+
7
+ export const generateCoverageHtmlDirectory = async (
8
+ coverage,
9
+ {
10
+ rootDirectoryUrl,
11
+ coverageHtmlDirectoryRelativeUrl,
12
+ coverageSkipEmpty,
13
+ coverageSkipFull,
14
+ },
15
+ ) => {
16
+ const libReport = requireFromJsenv("istanbul-lib-report")
17
+ const reports = requireFromJsenv("istanbul-reports")
18
+
19
+ const context = libReport.createContext({
20
+ dir: urlToFileSystemPath(rootDirectoryUrl),
21
+ coverageMap: istanbulCoverageMapFromCoverage(coverage),
22
+ sourceFinder: (path) => {
23
+ return readFileSync(
24
+ urlToFileSystemPath(resolveUrl(path, rootDirectoryUrl)),
25
+ "utf8",
26
+ )
27
+ },
28
+ })
29
+
30
+ const report = reports.create("html", {
31
+ skipEmpty: coverageSkipEmpty,
32
+ skipFull: coverageSkipFull,
33
+ subdir: coverageHtmlDirectoryRelativeUrl,
34
+ })
35
+ report.execute(context)
36
+ }
@@ -0,0 +1,22 @@
1
+ import { writeFile } from "@jsenv/filesystem"
2
+ import { urlToFileSystemPath } from "@jsenv/urls"
3
+ import { byteAsFileSize } from "@jsenv/log"
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)
22
+ }
@@ -0,0 +1,19 @@
1
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
2
+ import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js"
3
+
4
+ export const generateCoverageTextLog = (
5
+ coverage,
6
+ { coverageSkipEmpty, coverageSkipFull },
7
+ ) => {
8
+ const libReport = requireFromJsenv("istanbul-lib-report")
9
+ const reports = requireFromJsenv("istanbul-reports")
10
+
11
+ const context = libReport.createContext({
12
+ coverageMap: istanbulCoverageMapFromCoverage(coverage),
13
+ })
14
+ const report = reports.create("text", {
15
+ skipEmpty: coverageSkipEmpty,
16
+ skipFull: coverageSkipFull,
17
+ })
18
+ report.execute(context)
19
+ }
@@ -0,0 +1,52 @@
1
+ import { readFile } from "@jsenv/filesystem"
2
+ import { resolveUrl } from "@jsenv/urls"
3
+ import { Abort } from "@jsenv/abort"
4
+ import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js"
5
+
6
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
7
+ import { babelPluginInstrument } from "./babel_plugin_instrument.js"
8
+
9
+ export const relativeUrlToEmptyCoverage = async (
10
+ relativeUrl,
11
+ { signal, rootDirectoryUrl },
12
+ ) => {
13
+ const operation = Abort.startOperation()
14
+ operation.addAbortSignal(signal)
15
+
16
+ try {
17
+ const fileUrl = resolveUrl(relativeUrl, rootDirectoryUrl)
18
+ const content = await readFile(fileUrl, { as: "string" })
19
+
20
+ operation.throwIfAborted()
21
+ const { metadata } = await applyBabelPlugins({
22
+ babelPlugins: [[babelPluginInstrument, { rootDirectoryUrl }]],
23
+ urlInfo: {
24
+ originalUrl: fileUrl,
25
+ content,
26
+ },
27
+ })
28
+ const { coverage } = metadata
29
+ if (!coverage) {
30
+ throw new Error(`missing coverage for file`)
31
+ }
32
+ // https://github.com/gotwarlost/istanbul/blob/bc84c315271a5dd4d39bcefc5925cfb61a3d174a/lib/command/common/run-with-cover.js#L229
33
+ Object.keys(coverage.s).forEach(function (key) {
34
+ coverage.s[key] = 0
35
+ })
36
+ return coverage
37
+ } catch (e) {
38
+ if (e && e.code === "PARSE_ERROR") {
39
+ // return an empty coverage for that file when
40
+ // it contains a syntax error
41
+ return createEmptyCoverage(relativeUrl)
42
+ }
43
+ throw e
44
+ } finally {
45
+ await operation.end()
46
+ }
47
+ }
48
+
49
+ const createEmptyCoverage = (relativeUrl) => {
50
+ const { createFileCoverage } = requireFromJsenv("istanbul-lib-coverage")
51
+ return createFileCoverage(relativeUrl).toJSON()
52
+ }
@@ -0,0 +1,25 @@
1
+ import {
2
+ urlToRelativeUrl,
3
+ fileSystemPathToUrl,
4
+ isFileSystemPath,
5
+ } from "@jsenv/urls"
6
+
7
+ export const normalizeFileByFileCoveragePaths = (
8
+ fileByFileCoverage,
9
+ rootDirectoryUrl,
10
+ ) => {
11
+ const fileByFileNormalized = {}
12
+ Object.keys(fileByFileCoverage).forEach((key) => {
13
+ const fileCoverage = fileByFileCoverage[key]
14
+ const { path } = fileCoverage
15
+ const url = isFileSystemPath(path)
16
+ ? fileSystemPathToUrl(path)
17
+ : new URL(path, rootDirectoryUrl).href
18
+ const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
19
+ fileByFileNormalized[`./${relativeUrl}`] = {
20
+ ...fileCoverage,
21
+ path: `./${relativeUrl}`,
22
+ }
23
+ })
24
+ return fileByFileNormalized
25
+ }
@@ -0,0 +1,28 @@
1
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
2
+
3
+ export const composeTwoFileByFileIstanbulCoverages = (
4
+ firstFileByFileIstanbulCoverage,
5
+ secondFileByFileIstanbulCoverage,
6
+ ) => {
7
+ const fileByFileIstanbulCoverage = {}
8
+ Object.keys(firstFileByFileIstanbulCoverage).forEach((key) => {
9
+ fileByFileIstanbulCoverage[key] = firstFileByFileIstanbulCoverage[key]
10
+ })
11
+ Object.keys(secondFileByFileIstanbulCoverage).forEach((key) => {
12
+ const firstCoverage = firstFileByFileIstanbulCoverage[key]
13
+ const secondCoverage = secondFileByFileIstanbulCoverage[key]
14
+ fileByFileIstanbulCoverage[key] = firstCoverage
15
+ ? merge(firstCoverage, secondCoverage)
16
+ : secondCoverage
17
+ })
18
+
19
+ return fileByFileIstanbulCoverage
20
+ }
21
+
22
+ const merge = (firstIstanbulCoverage, secondIstanbulCoverage) => {
23
+ const { createFileCoverage } = requireFromJsenv("istanbul-lib-coverage")
24
+ const istanbulFileCoverageObject = createFileCoverage(firstIstanbulCoverage)
25
+ istanbulFileCoverageObject.merge(secondIstanbulCoverage)
26
+ const istanbulCoverage = istanbulFileCoverageObject.toJSON()
27
+ return istanbulCoverage
28
+ }
@@ -0,0 +1,16 @@
1
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
2
+
3
+ export const istanbulCoverageMapFromCoverage = (coverage) => {
4
+ const { createCoverageMap } = requireFromJsenv("istanbul-lib-coverage")
5
+
6
+ const coverageAdjusted = {}
7
+ Object.keys(coverage).forEach((key) => {
8
+ coverageAdjusted[key.slice(2)] = {
9
+ ...coverage[key],
10
+ path: key.slice(2),
11
+ }
12
+ })
13
+
14
+ const coverageMap = createCoverageMap(coverageAdjusted)
15
+ return coverageMap
16
+ }
@@ -0,0 +1,15 @@
1
+ import { collectFiles } from "@jsenv/filesystem"
2
+
3
+ export const listRelativeFileUrlToCover = async ({
4
+ signal,
5
+ rootDirectoryUrl,
6
+ coverageConfig,
7
+ }) => {
8
+ const matchingFileResultArray = await collectFiles({
9
+ signal,
10
+ directoryUrl: rootDirectoryUrl,
11
+ associations: { cover: coverageConfig },
12
+ predicate: ({ cover }) => cover,
13
+ })
14
+ return matchingFileResultArray.map(({ relativeUrl }) => relativeUrl)
15
+ }
@@ -0,0 +1,41 @@
1
+ import { Abort } from "@jsenv/abort"
2
+
3
+ import { listRelativeFileUrlToCover } from "./list_files_not_covered.js"
4
+ import { relativeUrlToEmptyCoverage } from "./empty_coverage_factory.js"
5
+
6
+ export const getMissingFileByFileCoverage = async ({
7
+ signal,
8
+ rootDirectoryUrl,
9
+ coverageConfig,
10
+ fileByFileCoverage,
11
+ }) => {
12
+ const relativeUrlsToCover = await listRelativeFileUrlToCover({
13
+ signal,
14
+ rootDirectoryUrl,
15
+ coverageConfig,
16
+ })
17
+ const relativeUrlsMissing = relativeUrlsToCover.filter((relativeUrlToCover) =>
18
+ Object.keys(fileByFileCoverage).every((key) => {
19
+ return key !== `./${relativeUrlToCover}`
20
+ }),
21
+ )
22
+
23
+ const operation = Abort.startOperation()
24
+ operation.addAbortSignal(signal)
25
+ const missingFileByFileCoverage = {}
26
+ await relativeUrlsMissing.reduce(async (previous, relativeUrlMissing) => {
27
+ operation.throwIfAborted()
28
+ await previous
29
+ await operation.withSignal(async (signal) => {
30
+ const emptyCoverage = await relativeUrlToEmptyCoverage(
31
+ relativeUrlMissing,
32
+ {
33
+ signal,
34
+ rootDirectoryUrl,
35
+ },
36
+ )
37
+ missingFileByFileCoverage[`./${relativeUrlMissing}`] = emptyCoverage
38
+ })
39
+ }, Promise.resolve())
40
+ return missingFileByFileCoverage
41
+ }