@jsenv/core 27.0.0-alpha.6 → 27.0.0-alpha.60

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 (150) hide show
  1. package/dist/event_source_client.js +545 -0
  2. package/dist/event_source_client.js.map +187 -0
  3. package/dist/html_supervisor_installer.js +1236 -0
  4. package/dist/html_supervisor_installer.js.map +337 -0
  5. package/dist/html_supervisor_setup.js +95 -0
  6. package/dist/html_supervisor_setup.js.map +57 -0
  7. package/dist/import_meta_hot.js +86 -0
  8. package/dist/import_meta_hot.js.map +42 -0
  9. package/main.js +8 -1
  10. package/package.json +30 -28
  11. package/readme.md +6 -14
  12. package/src/build/build.js +943 -555
  13. package/src/build/build_urls_generator.js +48 -23
  14. package/src/build/graph_utils.js +31 -0
  15. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  16. package/src/build/inject_service_worker_urls.js +79 -0
  17. package/src/build/resync_ressource_hints.js +68 -0
  18. package/src/build/start_build_server.js +192 -0
  19. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  20. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  21. package/src/dev/start_dev_server.js +136 -30
  22. package/src/execute/execute.js +31 -6
  23. package/src/execute/run.js +19 -56
  24. package/src/execute/runtimes/browsers/from_playwright.js +207 -147
  25. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  26. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  27. package/src/execute/runtimes/node/node_process.js +280 -39
  28. package/src/jsenv_root_directory_url.js +1 -0
  29. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  30. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  31. package/src/omega/compat/runtime_compat.js +50 -0
  32. package/src/omega/errors.js +51 -58
  33. package/src/omega/fetched_content_compliance.js +24 -0
  34. package/src/omega/file_url_converter.js +8 -50
  35. package/src/omega/kitchen.js +482 -304
  36. package/src/omega/omega_server.js +2 -3
  37. package/src/omega/server/file_service.js +53 -25
  38. package/src/omega/server/user_agent.js +4 -2
  39. package/src/omega/url_graph/url_graph_load.js +22 -7
  40. package/src/omega/url_graph/url_graph_report.js +98 -48
  41. package/src/omega/url_graph/url_info_transformations.js +26 -9
  42. package/src/omega/url_graph.js +80 -16
  43. package/src/omega/web_workers.js +42 -0
  44. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  45. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  46. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  47. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  48. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
  49. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +204 -0
  50. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
  51. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  52. package/src/plugins/bundling/css/bundle_css.js +140 -0
  53. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  54. package/src/plugins/bundling/js_module/bundle_js_module.js +309 -0
  55. package/src/plugins/bundling/jsenv_plugin_bundling.js +54 -0
  56. package/src/plugins/cache_control/jsenv_plugin_cache_control.js +34 -0
  57. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
  58. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  59. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
  60. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  61. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  62. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +242 -0
  63. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +79 -0
  64. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  65. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  66. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +83 -61
  67. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  68. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  69. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  70. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  71. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +105 -0
  72. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
  73. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  74. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  75. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +39 -33
  76. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
  77. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  78. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  79. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +65 -44
  80. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  81. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  82. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +297 -0
  83. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  84. package/src/plugins/minification/css/minify_css.js +9 -0
  85. package/src/plugins/minification/html/minify_html.js +15 -0
  86. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  87. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  88. package/src/plugins/minification/json/minify_json.js +8 -0
  89. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
  90. package/src/{omega → plugins}/plugin_controller.js +42 -11
  91. package/src/plugins/plugins.js +92 -0
  92. package/src/plugins/transpilation/as_js_classic/client/s.js +874 -0
  93. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  94. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  95. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  96. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +199 -0
  97. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +270 -0
  98. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +55 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  100. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  101. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
  102. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +12 -19
  103. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  104. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +45 -27
  105. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  106. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  107. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  108. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  109. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  110. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  111. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  112. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +181 -0
  113. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +80 -0
  114. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  115. package/src/plugins/url_analysis/css/css_urls.js +49 -0
  116. package/src/plugins/url_analysis/html/html_urls.js +269 -0
  117. package/src/plugins/url_analysis/js/js_urls.js +67 -0
  118. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +18 -0
  119. package/src/plugins/url_analysis/webmanifest/webmanifest_urls.js +17 -0
  120. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  121. package/src/plugins/url_version/jsenv_plugin_url_version.js +28 -0
  122. package/src/test/execute_plan.js +30 -18
  123. package/src/test/execute_test_plan.js +23 -8
  124. package/src/test/logs_file_execution.js +9 -8
  125. package/src/build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js +0 -225
  126. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  127. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  128. package/src/dev/plugins/autoreload/jsenv_plugin_autoreload.js +0 -374
  129. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  130. package/src/execute/runtimes/node/controlled_process.js +0 -316
  131. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  132. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_installer.js +0 -168
  133. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_setup.js +0 -77
  134. package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
  135. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  136. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  137. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  138. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  139. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  140. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  141. package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
  142. package/src/omega/core_plugins/url_version/jsenv_plugin_url_version.js +0 -50
  143. package/src/omega/core_plugins.js +0 -39
  144. package/src/omega/runtime_support/runtime_support.js +0 -20
  145. package/src/omega/url_graph/url_graph_sort.js +0 -29
  146. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  147. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  148. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  149. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  150. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -1,41 +1,62 @@
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 isSupported = (feature) =>
37
+ RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
38
+ const getImportSpecifier = (clientFileUrl) => {
39
+ const [reference] = context.referenceUtils.inject({
40
+ type: "js_import_export",
41
+ expectedType: "js_module",
42
+ specifier: clientFileUrl,
43
+ })
44
+ return JSON.parse(reference.generatedSpecifier)
45
+ }
46
+
18
47
  const babelPluginStructure = getBaseBabelPluginStructure({
19
48
  url: urlInfo.url,
20
- isSupportedOnRuntime,
21
- topLevelAwait,
22
- usesTopLevelAwait: urlInfo.data.usesTopLevelAwait,
49
+ isSupported,
50
+ isWorkerContext,
23
51
  isJsModule,
24
- isWorker,
52
+ getImportSpecifier,
25
53
  })
26
54
  if (getCustomBabelPlugins) {
27
55
  Object.assign(babelPluginStructure, getCustomBabelPlugins(context))
28
56
  }
29
57
 
30
58
  if (isJsModule) {
31
- const getImportSpecifier = (clientFileUrl) => {
32
- const [reference] = referenceUtils.inject({
33
- type: "js_import_export",
34
- specifier: clientFileUrl,
35
- })
36
- return JSON.parse(reference.generatedSpecifier)
37
- }
38
- if (!isSupportedOnRuntime("global_this")) {
59
+ if (!isSupported("global_this")) {
39
60
  babelPluginStructure["global-this-as-jsenv-import"] = [
40
61
  babelPluginGlobalThisAsJsenvImport,
41
62
  {
@@ -43,7 +64,7 @@ export const jsenvPluginBabel = ({
43
64
  },
44
65
  ]
45
66
  }
46
- if (!isSupportedOnRuntime("async_generator_function")) {
67
+ if (!isSupported("async_generator_function")) {
47
68
  babelPluginStructure["regenerator-runtime-as-jsenv-import"] = [
48
69
  babelPluginRegeneratorRuntimeAsJsenvImport,
49
70
  {
@@ -51,7 +72,7 @@ export const jsenvPluginBabel = ({
51
72
  },
52
73
  ]
53
74
  }
54
- if (!isSupportedOnRuntime("new_stylesheet")) {
75
+ if (!isSupported("new_stylesheet")) {
55
76
  babelPluginStructure["new-stylesheet-as-jsenv-import"] = [
56
77
  babelPluginNewStylesheetAsJsenvImport,
57
78
  {
@@ -76,22 +97,19 @@ export const jsenvPluginBabel = ({
76
97
  )
77
98
  const { code, map } = await applyBabelPlugins({
78
99
  babelPlugins,
79
- url: urlInfo.url,
80
- generatedUrl: urlInfo.generatedUrl,
81
- content: urlInfo.content,
100
+ urlInfo,
82
101
  })
83
102
  return {
84
103
  content: code,
85
104
  sourcemap: map,
86
105
  }
87
106
  }
88
-
89
107
  return {
90
108
  name: "jsenv:babel",
91
109
  appliesDuring: "*",
92
- transform: {
93
- js_module: transformWithBabel,
110
+ finalizeUrlContent: {
94
111
  js_classic: transformWithBabel,
112
+ js_module: transformWithBabel,
95
113
  },
96
114
  }
97
115
  }
@@ -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,181 @@
1
+ /*
2
+ * Jsenv wont touch code where "specifier" or "type" is dynamic (see code below)
3
+ * ```js
4
+ * const file = "./style.css"
5
+ * const type = "css"
6
+ * import(file, { assert: { type }})
7
+ * ```
8
+ * Jsenv could throw an error when it knows some browsers in runtimeCompat
9
+ * do not support import assertions
10
+ * But for now (as it is simpler) we let the browser throw the error
11
+ */
12
+
13
+ import { urlToFilename } from "@jsenv/filesystem"
14
+
15
+ import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
16
+ import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
17
+
18
+ import { fetchOriginalUrlInfo } from "../fetch_original_url_info.js"
19
+
20
+ export const jsenvPluginImportAssertions = () => {
21
+ const updateReference = (reference, searchParam) => {
22
+ reference.expectedType = "js_module"
23
+ reference.filename = `${urlToFilename(reference.url)}.js`
24
+ reference.mutation = (magicSource) => {
25
+ magicSource.remove({
26
+ start: reference.assertNode.start,
27
+ end: reference.assertNode.end,
28
+ })
29
+ }
30
+ const newUrl = injectQueryParams(reference.url, {
31
+ [searchParam]: "",
32
+ })
33
+ return newUrl
34
+ }
35
+
36
+ const importAssertions = {
37
+ name: "jsenv:import_assertions",
38
+ appliesDuring: "*",
39
+ redirectUrl: {
40
+ js_import_export: (reference, context) => {
41
+ if (!reference.assert) {
42
+ return null
43
+ }
44
+ // during build always replace import assertions with the js:
45
+ // - avoid rollup to see import assertions
46
+ // We would have to tell rollup to ignore import with assertion
47
+ // - means rollup can bundle more js file together
48
+ // - means url versioning can work for css inlined in js
49
+ if (reference.assert.type === "json") {
50
+ if (
51
+ context.scenario !== "build" &&
52
+ context.isSupportedOnCurrentClients("import_type_json")
53
+ ) {
54
+ return null
55
+ }
56
+ return updateReference(reference, "as_json_module")
57
+ }
58
+ if (reference.assert.type === "css") {
59
+ if (
60
+ context.scenario !== "build" &&
61
+ context.isSupportedOnCurrentClients("import_type_css")
62
+ ) {
63
+ return null
64
+ }
65
+ return updateReference(reference, "as_css_module")
66
+ }
67
+ if (reference.assert.type === "text") {
68
+ if (
69
+ context.scenario !== "build" &&
70
+ context.isSupportedOnCurrentClients("import_type_text")
71
+ ) {
72
+ return null
73
+ }
74
+ return updateReference(reference, "as_text_module")
75
+ }
76
+ return null
77
+ },
78
+ },
79
+ }
80
+ return [importAssertions, ...jsenvPluginAsModules()]
81
+ }
82
+
83
+ const jsenvPluginAsModules = () => {
84
+ const inlineContentClientFileUrl = new URL(
85
+ "../../inline/client/inline_content.js",
86
+ import.meta.url,
87
+ ).href
88
+
89
+ const asJsonModule = {
90
+ name: `jsenv:as_json_module`,
91
+ appliesDuring: "*",
92
+ fetchUrlContent: async (urlInfo, context) => {
93
+ const originalUrlInfo = await fetchOriginalUrlInfo({
94
+ urlInfo,
95
+ context,
96
+ searchParam: "as_json_module",
97
+ expectedType: "json",
98
+ })
99
+ if (!originalUrlInfo) {
100
+ return null
101
+ }
102
+ const jsonText = JSON.stringify(originalUrlInfo.content.trim())
103
+ return {
104
+ type: "js_module",
105
+ contentType: "text/javascript",
106
+ // here we could `export default ${jsonText}`:
107
+ // but js engine are optimized to recognize JSON.parse
108
+ // and use a faster parsing strategy
109
+ content: `export default JSON.parse(${jsonText})`,
110
+ }
111
+ },
112
+ }
113
+
114
+ const asCssModule = {
115
+ name: `jsenv:as_css_module`,
116
+ appliesDuring: "*",
117
+ fetchUrlContent: async (urlInfo, context) => {
118
+ const originalUrlInfo = await fetchOriginalUrlInfo({
119
+ urlInfo,
120
+ context,
121
+ searchParam: "as_css_module",
122
+ expectedType: "css",
123
+ })
124
+ if (!originalUrlInfo) {
125
+ return null
126
+ }
127
+ const cssText = JS_QUOTES.escapeSpecialChars(originalUrlInfo.content, {
128
+ // If template string is choosen and runtime do not support template literals
129
+ // it's ok because "jsenv:new_inline_content" plugin executes after this one
130
+ // and convert template strings into raw strings
131
+ canUseTemplateString: true,
132
+ })
133
+ return {
134
+ type: "js_module",
135
+ contentType: "text/javascript",
136
+ content: `import { InlineContent } from ${JSON.stringify(
137
+ inlineContentClientFileUrl,
138
+ )}
139
+
140
+ const inlineContent = new InlineContent(${cssText}, { type: "text/css" })
141
+ const stylesheet = new CSSStyleSheet()
142
+ stylesheet.replaceSync(inlineContent.text)
143
+ export default stylesheet`,
144
+ }
145
+ },
146
+ }
147
+
148
+ const asTextModule = {
149
+ name: `jsenv:as_text_module`,
150
+ appliesDuring: "*",
151
+ fetchUrlContent: async (urlInfo, context) => {
152
+ const originalUrlInfo = await fetchOriginalUrlInfo({
153
+ urlInfo,
154
+ context,
155
+ searchParam: "as_text_module",
156
+ expectedType: "text",
157
+ })
158
+ if (!originalUrlInfo) {
159
+ return null
160
+ }
161
+ const textPlain = JS_QUOTES.escapeSpecialChars(urlInfo.content, {
162
+ // If template string is choosen and runtime do not support template literals
163
+ // it's ok because "jsenv:new_inline_content" plugin executes after this one
164
+ // and convert template strings into raw strings
165
+ canUseTemplateString: true,
166
+ })
167
+ return {
168
+ type: "js_module",
169
+ contentType: "text/javascript",
170
+ content: `import { InlineContent } from ${JSON.stringify(
171
+ inlineContentClientFileUrl,
172
+ )}
173
+
174
+ const inlineContent = new InlineContent(${textPlain}, { type: "text/plain" })
175
+ export default inlineContent.text`,
176
+ }
177
+ },
178
+ }
179
+
180
+ return [asJsonModule, asCssModule, asTextModule]
181
+ }
@@ -0,0 +1,80 @@
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
+ // enable once https://github.com/rpetrich/babel-plugin-transform-async-to-promises/pull/83
28
+ // externalHelpers: true,
29
+ // externalHelpersPath: JSON.parse(
30
+ // context.referenceUtils.inject({
31
+ // type: "js_import_export",
32
+ // expectedType: "js_module",
33
+ // specifier:
34
+ // "babel-plugin-transform-async-to-promises/helpers.mjs",
35
+ // })[0],
36
+ // ),
37
+ },
38
+ ],
39
+ ],
40
+ })
41
+ return {
42
+ content: code,
43
+ sourcemap: map,
44
+ }
45
+ },
46
+ },
47
+ }
48
+ }
49
+
50
+ const usesTopLevelAwait = async (urlInfo) => {
51
+ if (!urlInfo.content.includes("await ")) {
52
+ return false
53
+ }
54
+ const { metadata } = await applyBabelPlugins({
55
+ urlInfo,
56
+ babelPlugins: [babelPluginMetadataUsesTopLevelAwait],
57
+ })
58
+ return metadata.usesTopLevelAwait
59
+ }
60
+
61
+ const babelPluginMetadataUsesTopLevelAwait = () => {
62
+ return {
63
+ name: "metadata-uses-top-level-await",
64
+ visitor: {
65
+ Program: (programPath, state) => {
66
+ let usesTopLevelAwait = false
67
+ programPath.traverse({
68
+ AwaitExpression: (path) => {
69
+ const closestFunction = path.getFunctionParent()
70
+ if (!closestFunction) {
71
+ usesTopLevelAwait = true
72
+ path.stop()
73
+ }
74
+ },
75
+ })
76
+ state.file.metadata.usesTopLevelAwait = usesTopLevelAwait
77
+ },
78
+ },
79
+ }
80
+ }
@@ -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
+ type,
18
+ specifier,
19
+ specifierStart,
20
+ specifierEnd,
21
+ specifierLine,
22
+ specifierColumn,
23
+ }) => {
24
+ const [reference] = context.referenceUtils.found({
25
+ type: `css_${type}`,
26
+ specifier,
27
+ specifierStart,
28
+ specifierEnd,
29
+ specifierLine,
30
+ specifierColumn,
31
+ })
32
+ actions.push(async () => {
33
+ magicSource.replace({
34
+ start: specifierStart,
35
+ end: specifierEnd,
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
+ }