@jsenv/core 27.0.0-alpha.4 → 27.0.0-alpha.40

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 (141) hide show
  1. package/dist/event_source_client.js +549 -0
  2. package/dist/event_source_client.js.map +188 -0
  3. package/dist/html_supervisor_installer.js +1145 -0
  4. package/dist/html_supervisor_installer.js.map +322 -0
  5. package/dist/html_supervisor_setup.js +92 -0
  6. package/dist/html_supervisor_setup.js.map +57 -0
  7. package/main.js +8 -1
  8. package/package.json +22 -21
  9. package/readme.md +4 -12
  10. package/src/build/build.js +731 -433
  11. package/src/build/build_urls_generator.js +55 -21
  12. package/src/build/graph_utils.js +31 -0
  13. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  14. package/src/build/inject_service_worker_urls.js +79 -0
  15. package/src/build/resync_ressource_hints.js +68 -0
  16. package/src/build/start_build_server.js +205 -0
  17. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  18. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  19. package/src/dev/start_dev_server.js +58 -26
  20. package/src/execute/execute.js +30 -4
  21. package/src/execute/run.js +19 -56
  22. package/src/execute/runtimes/browsers/from_playwright.js +201 -147
  23. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  24. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  25. package/src/execute/runtimes/node/node_process.js +280 -39
  26. package/src/jsenv_root_directory_url.js +1 -0
  27. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  28. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  29. package/src/omega/compat/runtime_compat.js +50 -0
  30. package/src/omega/errors.js +51 -58
  31. package/src/omega/fetched_content_compliance.js +24 -0
  32. package/src/omega/file_url_converter.js +8 -50
  33. package/src/omega/kitchen.js +414 -285
  34. package/src/omega/server/file_service.js +21 -22
  35. package/src/omega/url_graph/url_graph_load.js +14 -7
  36. package/src/omega/url_graph/url_graph_report.js +17 -15
  37. package/src/omega/url_graph/url_info_transformations.js +17 -5
  38. package/src/omega/url_graph.js +33 -10
  39. package/src/omega/web_workers.js +42 -0
  40. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  41. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  42. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  43. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  44. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
  45. package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +31 -172
  46. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
  47. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  48. package/src/plugins/bundling/css/bundle_css.js +21 -0
  49. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  50. package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +120 -79
  51. package/src/plugins/bundling/jsenv_plugin_bundling.js +51 -0
  52. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
  53. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  54. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
  55. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  56. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  57. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_installer.js +3 -2
  58. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_setup.js +0 -0
  59. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  60. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  61. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +52 -55
  62. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  63. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  64. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  65. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  66. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +101 -0
  67. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
  68. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  69. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  70. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +37 -31
  71. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
  72. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  73. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  74. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +61 -40
  75. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  76. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  77. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
  78. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  79. package/src/plugins/minification/css/minify_css.js +9 -0
  80. package/src/plugins/minification/html/minify_html.js +15 -0
  81. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  82. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  83. package/src/plugins/minification/json/minify_json.js +8 -0
  84. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
  85. package/src/{omega → plugins}/plugin_controller.js +39 -11
  86. package/src/plugins/plugins.js +89 -0
  87. package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
  88. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  89. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  90. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  91. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
  92. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
  93. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +93 -0
  94. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  95. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  96. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
  97. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
  98. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
  100. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  101. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  102. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  103. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  104. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  105. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  106. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  107. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +200 -0
  108. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
  109. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  110. package/src/plugins/url_references/css/css_urls.js +49 -0
  111. package/src/plugins/url_references/html/html_urls.js +273 -0
  112. package/src/plugins/url_references/js/js_urls.js +43 -0
  113. package/src/plugins/url_references/jsenv_plugin_imports_analysis.js +46 -0
  114. package/src/plugins/url_references/jsenv_plugin_url_analysis.js +18 -0
  115. package/src/plugins/url_references/jsenv_plugin_url_references.js +6 -0
  116. package/src/plugins/url_references/webmanifest/webmanifest_urls.js +17 -0
  117. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  118. package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
  119. package/src/test/execute_plan.js +28 -11
  120. package/src/test/execute_test_plan.js +23 -8
  121. package/src/test/logs_file_execution.js +8 -7
  122. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  123. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  124. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  125. package/src/execute/runtimes/node/controlled_process.js +0 -316
  126. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  127. package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
  128. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  129. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  130. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  131. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  132. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  133. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  134. package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
  135. package/src/omega/core_plugins.js +0 -39
  136. package/src/omega/runtime_support/runtime_support.js +0 -20
  137. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  138. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  139. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  140. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  141. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -1,27 +1,45 @@
1
1
  import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
2
2
 
3
+ import { RUNTIME_COMPAT } from "@jsenv/core/src/omega/compat/runtime_compat.js"
3
4
  import { getBaseBabelPluginStructure } from "./helpers/babel_plugin_structure.js"
4
5
  import { babelPluginBabelHelpersAsJsenvImports } from "./helpers/babel_plugin_babel_helpers_as_jsenv_imports.js"
5
6
  import { babelPluginNewStylesheetAsJsenvImport } from "./new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js"
6
7
  import { babelPluginGlobalThisAsJsenvImport } from "./global_this/babel_plugin_global_this_as_jsenv_import.js"
7
8
  import { babelPluginRegeneratorRuntimeAsJsenvImport } from "./regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js"
8
9
 
9
- export const jsenvPluginBabel = ({
10
- getCustomBabelPlugins,
11
- topLevelAwait,
12
- } = {}) => {
10
+ export const jsenvPluginBabel = ({ getCustomBabelPlugins } = {}) => {
13
11
  const transformWithBabel = async (urlInfo, context) => {
14
12
  const isJsModule = urlInfo.type === "js_module"
15
- const isWorker =
16
- urlInfo.subtype === "worker" || urlInfo.subtype === "service_worker"
17
- const { isSupportedOnRuntime, referenceUtils } = context
13
+ const isWorker = urlInfo.subtype === "worker"
14
+ const isServiceWorker = urlInfo.subtype === "service_worker"
15
+ const isSharedWorker = urlInfo.subtype === "shared_worker"
16
+ const isWorkerContext = isWorker || isServiceWorker || isSharedWorker
17
+
18
+ let { clientRuntimeCompat } = context
19
+ if (isWorker) {
20
+ clientRuntimeCompat = RUNTIME_COMPAT.add(clientRuntimeCompat, "worker")
21
+ } else if (isServiceWorker) {
22
+ // when code is executed by a service worker we can assume
23
+ // the execution context supports more than the default one
24
+ // for instance arrow function are supported
25
+ clientRuntimeCompat = RUNTIME_COMPAT.add(
26
+ clientRuntimeCompat,
27
+ "service_worker",
28
+ )
29
+ } else if (isSharedWorker) {
30
+ clientRuntimeCompat = RUNTIME_COMPAT.add(
31
+ clientRuntimeCompat,
32
+ "shared_worker",
33
+ )
34
+ }
35
+
36
+ const { referenceUtils } = context
37
+ const isSupported = (feature) =>
38
+ RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
18
39
  const babelPluginStructure = getBaseBabelPluginStructure({
19
40
  url: urlInfo.url,
20
- isSupportedOnRuntime,
21
- topLevelAwait,
22
- usesTopLevelAwait: urlInfo.data.usesTopLevelAwait,
23
- isJsModule,
24
- isWorker,
41
+ isSupported,
42
+ isWorkerContext,
25
43
  })
26
44
  if (getCustomBabelPlugins) {
27
45
  Object.assign(babelPluginStructure, getCustomBabelPlugins(context))
@@ -31,11 +49,12 @@ export const jsenvPluginBabel = ({
31
49
  const getImportSpecifier = (clientFileUrl) => {
32
50
  const [reference] = referenceUtils.inject({
33
51
  type: "js_import_export",
52
+ expectedType: "js_module",
34
53
  specifier: clientFileUrl,
35
54
  })
36
55
  return JSON.parse(reference.generatedSpecifier)
37
56
  }
38
- if (!isSupportedOnRuntime("global_this")) {
57
+ if (!isSupported("global_this")) {
39
58
  babelPluginStructure["global-this-as-jsenv-import"] = [
40
59
  babelPluginGlobalThisAsJsenvImport,
41
60
  {
@@ -43,7 +62,7 @@ export const jsenvPluginBabel = ({
43
62
  },
44
63
  ]
45
64
  }
46
- if (!isSupportedOnRuntime("async_generator_function")) {
65
+ if (!isSupported("async_generator_function")) {
47
66
  babelPluginStructure["regenerator-runtime-as-jsenv-import"] = [
48
67
  babelPluginRegeneratorRuntimeAsJsenvImport,
49
68
  {
@@ -51,7 +70,7 @@ export const jsenvPluginBabel = ({
51
70
  },
52
71
  ]
53
72
  }
54
- if (!isSupportedOnRuntime("new_stylesheet")) {
73
+ if (!isSupported("new_stylesheet")) {
55
74
  babelPluginStructure["new-stylesheet-as-jsenv-import"] = [
56
75
  babelPluginNewStylesheetAsJsenvImport,
57
76
  {
@@ -76,22 +95,19 @@ export const jsenvPluginBabel = ({
76
95
  )
77
96
  const { code, map } = await applyBabelPlugins({
78
97
  babelPlugins,
79
- url: urlInfo.url,
80
- generatedUrl: urlInfo.generatedUrl,
81
- content: urlInfo.content,
98
+ urlInfo,
82
99
  })
83
100
  return {
84
101
  content: code,
85
102
  sourcemap: map,
86
103
  }
87
104
  }
88
-
89
105
  return {
90
106
  name: "jsenv:babel",
91
107
  appliesDuring: "*",
92
- transform: {
93
- js_module: transformWithBabel,
108
+ finalizeUrlContent: {
94
109
  js_classic: transformWithBabel,
110
+ js_module: transformWithBabel,
95
111
  },
96
112
  }
97
113
  }
@@ -1,9 +1,3 @@
1
- /*
2
- * TODO:
3
- * - code should also inject helper when code uses new keyword on "CSSStyleSheet"
4
- * - code should also inject helper when code uses "document.adoptedStylesheets"
5
- */
6
-
7
1
  import { pathToFileURL } from "node:url"
8
2
 
9
3
  import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js"
@@ -27,6 +21,18 @@ export const babelPluginNewStylesheetAsJsenvImport = (
27
21
  }
28
22
  let usesNewStylesheet = false
29
23
  programPath.traverse({
24
+ NewExpression: (path) => {
25
+ usesNewStylesheet = isNewCssStyleSheetCall(path.node)
26
+ if (usesNewStylesheet) {
27
+ path.stop()
28
+ }
29
+ },
30
+ MemberExpression: (path) => {
31
+ usesNewStylesheet = isDocumentAdoptedStyleSheets(path.node)
32
+ if (usesNewStylesheet) {
33
+ path.stop()
34
+ }
35
+ },
30
36
  CallExpression: (path) => {
31
37
  if (path.node.callee.type !== "Import") {
32
38
  // Some other function call, not import();
@@ -90,6 +96,24 @@ export const babelPluginNewStylesheetAsJsenvImport = (
90
96
  }
91
97
  }
92
98
 
99
+ const isNewCssStyleSheetCall = (node) => {
100
+ return (
101
+ node.type === "NewExpression" &&
102
+ node.callee.type === "Identifier" &&
103
+ node.callee.name === "CSSStyleSheet"
104
+ )
105
+ }
106
+
107
+ const isDocumentAdoptedStyleSheets = (node) => {
108
+ return (
109
+ node.type === "MemberExpression" &&
110
+ node.object.type === "Identifier" &&
111
+ node.object.name === "document" &&
112
+ node.property.type === "Identifier" &&
113
+ node.property.name === "adoptedStyleSheets"
114
+ )
115
+ }
116
+
93
117
  const hasCssModuleQueryParam = (path) => {
94
118
  const { node } = path
95
119
  return (
@@ -0,0 +1,18 @@
1
+ import { transpileWithParcel } from "@jsenv/utils/css_ast/parcel_css.js"
2
+
3
+ // https://github.com/parcel-bundler/parcel-css
4
+ export const jsenvPluginCssParcel = () => {
5
+ return {
6
+ name: "jsenv:css_parcel",
7
+ appliesDuring: "*",
8
+ transformUrlContent: {
9
+ css: (urlInfo, context) => {
10
+ const { code, map } = transpileWithParcel(urlInfo, context)
11
+ return {
12
+ content: String(code),
13
+ sourcemap: map,
14
+ }
15
+ },
16
+ },
17
+ }
18
+ }
@@ -0,0 +1,30 @@
1
+ export const fetchOriginalUrlInfo = async ({
2
+ urlInfo,
3
+ context,
4
+ searchParam,
5
+ expectedType,
6
+ }) => {
7
+ const urlObject = new URL(urlInfo.url)
8
+ const { searchParams } = urlObject
9
+ if (!searchParams.has(searchParam)) {
10
+ return null
11
+ }
12
+ searchParams.delete(searchParam)
13
+ const originalUrl = urlObject.href
14
+ const originalReference = {
15
+ ...(context.reference.original || context.reference),
16
+ expectedType,
17
+ }
18
+ originalReference.url = originalUrl
19
+ const originalUrlInfo = context.urlGraph.reuseOrCreateUrlInfo(
20
+ originalReference.url,
21
+ )
22
+ await context.fetchUrlContent({
23
+ reference: originalReference,
24
+ urlInfo: originalUrlInfo,
25
+ })
26
+ if (originalUrlInfo.dependents.size === 0) {
27
+ context.urlGraph.deleteUrlInfo(originalUrlInfo.url)
28
+ }
29
+ return originalUrlInfo
30
+ }
@@ -0,0 +1,200 @@
1
+ import { urlToFilename } from "@jsenv/filesystem"
2
+
3
+ import { parseJsImportAssertions } from "@jsenv/utils/js_ast/parse_js_import_assertions.js"
4
+ import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
5
+ import { injectQueryParamsIntoSpecifier } from "@jsenv/utils/urls/url_utils.js"
6
+ import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
7
+
8
+ import { fetchOriginalUrlInfo } from "../fetch_original_url_info.js"
9
+
10
+ export const jsenvPluginImportAssertions = () => {
11
+ const importAssertions = {
12
+ name: "jsenv:import_assertions",
13
+ appliesDuring: "*",
14
+ transformUrlContent: {
15
+ js_module: async (urlInfo, context) => {
16
+ // "usesImportAssertion" is set by "jsenv:imports_analysis"
17
+ if (urlInfo.data.usesImportAssertion === false) {
18
+ return null
19
+ }
20
+ const importTypesToTranspile = getImportTypesToTranspile(context)
21
+ if (importTypesToTranspile.length === 0) {
22
+ return null
23
+ }
24
+ const importAssertions = await parseJsImportAssertions({
25
+ js: urlInfo.content,
26
+ url: (urlInfo.data && urlInfo.data.rawUrl) || urlInfo.url,
27
+ })
28
+ const magicSource = createMagicSource(urlInfo.content)
29
+ importAssertions.forEach((importAssertion) => {
30
+ const assertType = importAssertion.assert.type
31
+ if (!importTypesToTranspile.includes(assertType)) {
32
+ return
33
+ }
34
+ const { searchParam } = importAsInfos[assertType]
35
+ const reference = context.referenceUtils.findByGeneratedSpecifier(
36
+ JSON.stringify(importAssertion.specifier),
37
+ )
38
+ const [newReference] = context.referenceUtils.update(reference, {
39
+ expectedType: "js_module",
40
+ specifier: injectQueryParamsIntoSpecifier(
41
+ importAssertion.specifier,
42
+ {
43
+ [searchParam]: "",
44
+ },
45
+ ),
46
+ filename: `${urlToFilename(reference.url)}.js`,
47
+ })
48
+ magicSource.replace({
49
+ start: importAssertion.specifierStart,
50
+ end: importAssertion.specifierEnd,
51
+ replacement: newReference.generatedSpecifier,
52
+ })
53
+ magicSource.remove({
54
+ start: importAssertion.assertNode.start,
55
+ end: importAssertion.assertNode.end,
56
+ })
57
+ })
58
+ return magicSource.toContentAndSourcemap()
59
+ },
60
+ },
61
+ }
62
+ return [importAssertions, ...jsenvPluginAsModules()]
63
+ }
64
+
65
+ const jsenvPluginAsModules = () => {
66
+ const inlineContentClientFileUrl = new URL(
67
+ "../../inline/client/inline_content.js",
68
+ import.meta.url,
69
+ ).href
70
+
71
+ const asJsonModule = {
72
+ name: `jsenv:as_json_module`,
73
+ appliesDuring: "*",
74
+ fetchUrlContent: async (urlInfo, context) => {
75
+ const originalUrlInfo = await fetchOriginalUrlInfo({
76
+ urlInfo,
77
+ context,
78
+ searchParam: "as_json_module",
79
+ expectedType: "json",
80
+ })
81
+ if (!originalUrlInfo) {
82
+ return null
83
+ }
84
+ const jsonText = JSON.stringify(originalUrlInfo.content.trim())
85
+ return {
86
+ type: "js_module",
87
+ contentType: "text/javascript",
88
+ // here we could `export default ${jsonText}`:
89
+ // but js engine are optimized to recognize JSON.parse
90
+ // and use a faster parsing strategy
91
+ content: `export default JSON.parse(${jsonText})`,
92
+ }
93
+ },
94
+ }
95
+
96
+ const asCssModule = {
97
+ name: `jsenv:as_css_module`,
98
+ appliesDuring: "*",
99
+ fetchUrlContent: async (urlInfo, context) => {
100
+ const originalUrlInfo = await fetchOriginalUrlInfo({
101
+ urlInfo,
102
+ context,
103
+ searchParam: "as_css_module",
104
+ expectedType: "css",
105
+ })
106
+ if (!originalUrlInfo) {
107
+ return null
108
+ }
109
+ const cssText = JS_QUOTES.escapeSpecialChars(originalUrlInfo.content, {
110
+ // If template string is choosen and runtime do not support template literals
111
+ // it's ok because "jsenv:new_inline_content" plugin executes after this one
112
+ // and convert template strings into raw strings
113
+ canUseTemplateString: true,
114
+ })
115
+ return {
116
+ type: "js_module",
117
+ contentType: "text/javascript",
118
+ content: `import { InlineContent } from ${JSON.stringify(
119
+ inlineContentClientFileUrl,
120
+ )}
121
+
122
+ const inlineContent = new InlineContent(${cssText}, { type: "text/css" })
123
+ const stylesheet = new CSSStyleSheet()
124
+ stylesheet.replaceSync(inlineContent.text)
125
+ export default stylesheet`,
126
+ }
127
+ },
128
+ }
129
+
130
+ const asTextModule = {
131
+ name: `jsenv:as_text_module`,
132
+ appliesDuring: "*",
133
+ fetchUrlContent: async (urlInfo, context) => {
134
+ const originalUrlInfo = await fetchOriginalUrlInfo({
135
+ urlInfo,
136
+ context,
137
+ searchParam: "as_text_module",
138
+ expectedType: "text",
139
+ })
140
+ if (!originalUrlInfo) {
141
+ return null
142
+ }
143
+ const textPlain = JS_QUOTES.escapeSpecialChars(urlInfo.content, {
144
+ // If template string is choosen and runtime do not support template literals
145
+ // it's ok because "jsenv:new_inline_content" plugin executes after this one
146
+ // and convert template strings into raw strings
147
+ canUseTemplateString: true,
148
+ })
149
+ return {
150
+ type: "js_module",
151
+ contentType: "text/javascript",
152
+ content: `import { InlineContent } from ${JSON.stringify(
153
+ inlineContentClientFileUrl,
154
+ )}
155
+
156
+ const inlineContent = new InlineContent(${textPlain}, { type: "text/plain" })
157
+ export default inlineContent.text`,
158
+ }
159
+ },
160
+ }
161
+
162
+ return [asJsonModule, asCssModule, asTextModule]
163
+ }
164
+
165
+ const importAsInfos = {
166
+ json: {
167
+ searchParam: "as_json_module",
168
+ },
169
+ css: {
170
+ searchParam: "as_css_module",
171
+ },
172
+ text: {
173
+ searchParam: "as_text_module",
174
+ },
175
+ }
176
+
177
+ const getImportTypesToTranspile = ({
178
+ scenario,
179
+ isSupportedOnCurrentClients,
180
+ }) => {
181
+ // during build always replace import assertions with the js:
182
+ // - avoid rollup to see import assertions
183
+ // We would have to tell rollup to ignore import with assertion
184
+ // - means rollup can bundle more js file together
185
+ // - means url versioning can work for css inlined in js
186
+ if (scenario === "build") {
187
+ return ["json", "css", "text"]
188
+ }
189
+ const importTypes = []
190
+ if (!isSupportedOnCurrentClients("import_type_json")) {
191
+ importTypes.push("json")
192
+ }
193
+ if (!isSupportedOnCurrentClients("import_type_css")) {
194
+ importTypes.push("css")
195
+ }
196
+ if (!isSupportedOnCurrentClients("import_type_text")) {
197
+ importTypes.push("text")
198
+ }
199
+ return importTypes
200
+ }
@@ -0,0 +1,70 @@
1
+ import { requireBabelPlugin } from "@jsenv/babel-plugins"
2
+
3
+ import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
4
+
5
+ export const jsenvPluginTopLevelAwait = () => {
6
+ return {
7
+ name: "jsenv:top_level_await",
8
+ appliesDuring: "*",
9
+ transformUrlContent: {
10
+ js_module: async (urlInfo, context) => {
11
+ if (context.isSupportedOnCurrentClients("top_level_await")) {
12
+ return null
13
+ }
14
+ const usesTLA = await usesTopLevelAwait(urlInfo)
15
+ if (!usesTLA) {
16
+ return null
17
+ }
18
+ const { code, map } = await applyBabelPlugins({
19
+ urlInfo,
20
+ babelPlugins: [
21
+ [
22
+ requireBabelPlugin("babel-plugin-transform-async-to-promises"),
23
+ {
24
+ // Maybe we could pass target: "es6" when we support arrow function
25
+ // https://github.com/rpetrich/babel-plugin-transform-async-to-promises/blob/92755ff8c943c97596523e586b5fa515c2e99326/async-to-promises.ts#L55
26
+ topLevelAwait: "simple",
27
+ },
28
+ ],
29
+ ],
30
+ })
31
+ return {
32
+ content: code,
33
+ sourcemap: map,
34
+ }
35
+ },
36
+ },
37
+ }
38
+ }
39
+
40
+ const usesTopLevelAwait = async (urlInfo) => {
41
+ if (!urlInfo.content.includes("await ")) {
42
+ return false
43
+ }
44
+ const { metadata } = await applyBabelPlugins({
45
+ urlInfo,
46
+ babelPlugins: [babelPluginMetadataUsesTopLevelAwait],
47
+ })
48
+ return metadata.usesTopLevelAwait
49
+ }
50
+
51
+ const babelPluginMetadataUsesTopLevelAwait = () => {
52
+ return {
53
+ name: "metadata-uses-top-level-await",
54
+ visitor: {
55
+ Program: (programPath, state) => {
56
+ let usesTopLevelAwait = false
57
+ programPath.traverse({
58
+ AwaitExpression: (path) => {
59
+ const closestFunction = path.getFunctionParent()
60
+ if (!closestFunction) {
61
+ usesTopLevelAwait = true
62
+ path.stop()
63
+ }
64
+ },
65
+ })
66
+ state.file.metadata.usesTopLevelAwait = usesTopLevelAwait
67
+ },
68
+ },
69
+ }
70
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Transforms code to make it compatible with browser that would not be able to
3
+ * run it otherwise. For instance:
4
+ * - const -> var
5
+ * - async/await -> promises
6
+ * Anything that is not standard (import.meta.dev for instance) is outside the scope
7
+ * of this plugin
8
+ */
9
+
10
+ import { jsenvPluginCssParcel } from "./css_parcel/jsenv_plugin_css_parcel.js"
11
+ import { jsenvPluginImportAssertions } from "./import_assertions/jsenv_plugin_import_assertions.js"
12
+ import { jsenvPluginAsJsClassic } from "./as_js_classic/jsenv_plugin_as_js_classic.js"
13
+ import { jsenvPluginBabel } from "./babel/jsenv_plugin_babel.js"
14
+ import { jsenvPluginTopLevelAwait } from "./jsenv_plugin_top_level_await.js"
15
+
16
+ export const jsenvPluginTranspilation = ({
17
+ importAssertions = true,
18
+ css = true,
19
+ jsModuleAsJsClassic = true,
20
+ systemJsInjection = true,
21
+ topLevelAwait = true,
22
+ getCustomBabelPlugins,
23
+ }) => {
24
+ return [
25
+ // import assertions we want it all the time
26
+ ...(importAssertions ? [jsenvPluginImportAssertions()] : []),
27
+ // babel also so that rollup can bundle babel helpers for instance
28
+ jsenvPluginBabel({
29
+ topLevelAwait,
30
+ getCustomBabelPlugins,
31
+ }),
32
+ // but the conversion from js_module to js_classic
33
+ // we want to do it after bundling
34
+ // so the build function will disable jsModuleAsJsClassic during build
35
+ // and enable it manually during postbuild
36
+ ...(jsModuleAsJsClassic
37
+ ? [jsenvPluginAsJsClassic({ systemJsInjection })]
38
+ : []),
39
+ // topLevelAwait must come after js_module_as_js_classic because it's related to the module format
40
+ // so we want to wait to know the module format before transforming things related to top level await
41
+ ...(topLevelAwait ? [jsenvPluginTopLevelAwait(topLevelAwait)] : []),
42
+ ...(css ? [jsenvPluginCssParcel()] : []),
43
+ ]
44
+ }
@@ -0,0 +1,49 @@
1
+ /*
2
+ * https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/css/src/CSSTransformer.js
3
+ */
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"
8
+
9
+ export const parseAndTransformCssUrls = async (urlInfo, context) => {
10
+ const actions = []
11
+ const magicSource = createMagicSource(urlInfo.content)
12
+ await applyPostCss({
13
+ sourcemaps: false,
14
+ plugins: [
15
+ postCssPluginUrlVisitor({
16
+ urlVisitor: ({
17
+ declarationNode,
18
+ type,
19
+ specifier,
20
+ line,
21
+ column,
22
+ start,
23
+ end,
24
+ }) => {
25
+ const [reference] = context.referenceUtils.found({
26
+ node: declarationNode,
27
+ type: `css_${type}`,
28
+ specifier,
29
+ line,
30
+ column,
31
+ })
32
+ actions.push(async () => {
33
+ magicSource.replace({
34
+ start,
35
+ end,
36
+ replacement: await context.referenceUtils.readGeneratedSpecifier(
37
+ reference,
38
+ ),
39
+ })
40
+ })
41
+ },
42
+ }),
43
+ ],
44
+ url: urlInfo.data.rawUrl || urlInfo.url,
45
+ content: urlInfo.content,
46
+ })
47
+ await Promise.all(actions.map((action) => action()))
48
+ return magicSource.toContentAndSourcemap()
49
+ }