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

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 +549 -0
  2. package/dist/event_source_client.js.map +188 -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 +36 -29
  11. package/readme.md +6 -14
  12. package/src/build/build.js +961 -559
  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 +200 -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 +150 -34
  22. package/src/execute/execute.js +33 -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 +475 -308
  36. package/src/omega/omega_server.js +2 -3
  37. package/src/omega/server/file_service.js +57 -26
  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 +94 -51
  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 +19 -12
  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 +7 -4
  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 +38 -19
  123. package/src/test/execute_test_plan.js +25 -8
  124. package/src/test/logs_file_execution.js +10 -12
  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
@@ -0,0 +1 @@
1
+ s.js exists to ease jsenv ability to find the file.
@@ -0,0 +1,47 @@
1
+ import babelParser from "@babel/parser"
2
+
3
+ export const babelPluginTransformImportMetaUrl = (babel) => {
4
+ return {
5
+ name: "transform-import-meta-url",
6
+ visitor: {
7
+ Program: (programPath) => {
8
+ const currentUrlIdentifier =
9
+ programPath.scope.generateUidIdentifier("currentUrl")
10
+ let used = false
11
+
12
+ programPath.traverse({
13
+ MemberExpression: (path) => {
14
+ const node = path.node
15
+ if (
16
+ node.object.type === "MetaProperty" &&
17
+ node.object.property.name === "meta" &&
18
+ node.property.name === "url"
19
+ ) {
20
+ // const node = babel.types.valueToNode(10)
21
+ const identifier = babel.types.identifier(
22
+ currentUrlIdentifier.name,
23
+ )
24
+ const expressionStatement =
25
+ babel.types.expressionStatement(identifier)
26
+ path.replaceWith(expressionStatement)
27
+ used = true
28
+ }
29
+ },
30
+ })
31
+ if (used) {
32
+ const ast = generateExpressionAst(`document.currentScript.src`)
33
+ programPath.scope.push({
34
+ id: currentUrlIdentifier,
35
+ init: ast,
36
+ })
37
+ }
38
+ },
39
+ },
40
+ }
41
+ }
42
+
43
+ const generateExpressionAst = (expression, options) => {
44
+ const { parseExpression } = babelParser
45
+ const ast = parseExpression(expression, options)
46
+ return ast
47
+ }
@@ -0,0 +1,43 @@
1
+ // const { clientRuntimeCompat, isSupportedOnCurrentClient } = context
2
+ // const shouldBeCompatibleWithNode =
3
+ // Object.keys(clientRuntimeCompat).includes("node")
4
+ // const requiredFeatureNames = [
5
+ // "import_dynamic",
6
+ // "top_level_await",
7
+ // "global_this",
8
+ // // when using node we assume the code won't use browser specific feature
9
+ // ...(shouldBeCompatibleWithNode
10
+ // ? []
11
+ // : [
12
+ // "script_type_module",
13
+ // "worker_type_module",
14
+ // "import_type_json",
15
+ // "import_type_css",
16
+ // ]),
17
+ // // "importmap",
18
+ // ]
19
+ // const needsSystemJs = featuresRelatedToSystemJs.some((featureName) => {
20
+ // const isRequired = requiredFeatureNames.includes(featureName)
21
+ // return isRequired && !isSupportedOnCurrentClient(featureName)
22
+ // })
23
+ // if (!needsSystemJs) {
24
+ // return null
25
+ // }
26
+ // const { code, map } = await applyBabelPlugins({
27
+
28
+ // })
29
+ // return {
30
+ // content: code,
31
+ // soourcemap: map,
32
+ // }
33
+
34
+ // const featuresRelatedToSystemJs = [
35
+ // "script_type_module",
36
+ // "worker_type_module",
37
+ // "import_dynamic",
38
+ // "import_type_json",
39
+ // "import_type_css",
40
+ // "top_level_await",
41
+ // // "importmap",
42
+ // // "worker_importmap",
43
+ // ]
@@ -0,0 +1,199 @@
1
+ /*
2
+ * Something to keep in mind:
3
+ * When systemjs format is used by babel, it will generated UID based on
4
+ * the import specifier:
5
+ * https://github.com/babel/babel/blob/97d1967826077f15e766778c0d64711399e9a72a/packages/babel-plugin-transform-modules-systemjs/src/index.ts#L498
6
+ * But at this stage import specifier are absolute file urls
7
+ * So without minification these specifier are long and dependent
8
+ * on where the files are on the filesystem.
9
+ * This is mitigated by minification that will shorten them
10
+ * But ideally babel should not generate this in the first place
11
+ * and prefer to unique identifier based solely on the specifier basename for instance
12
+ */
13
+
14
+ import { createRequire } from "node:module"
15
+ import { readFileSync, urlToFilename } from "@jsenv/filesystem"
16
+
17
+ import { requireBabelPlugin } from "@jsenv/babel-plugins"
18
+ import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
19
+ import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
20
+ import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
21
+ import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_composition_v3.js"
22
+
23
+ import { fetchOriginalUrlInfo } from "../fetch_original_url_info.js"
24
+ import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
25
+ import { jsenvPluginScriptTypeModuleAsClassic } from "./jsenv_plugin_script_type_module_as_classic.js"
26
+ import { jsenvPluginWorkersTypeModuleAsClassic } from "./jsenv_plugin_workers_type_module_as_classic.js"
27
+
28
+ const require = createRequire(import.meta.url)
29
+
30
+ export const jsenvPluginAsJsClassic = ({ systemJsInjection }) => {
31
+ const systemJsClientFileUrl = new URL("./client/s.js", import.meta.url).href
32
+
33
+ return [
34
+ asJsClassic({ systemJsInjection, systemJsClientFileUrl }),
35
+ jsenvPluginScriptTypeModuleAsClassic({
36
+ systemJsInjection,
37
+ systemJsClientFileUrl,
38
+ generateJsClassicFilename,
39
+ }),
40
+ jsenvPluginWorkersTypeModuleAsClassic({
41
+ generateJsClassicFilename,
42
+ }),
43
+ ]
44
+ }
45
+
46
+ const asJsClassic = ({ systemJsInjection, systemJsClientFileUrl }) => {
47
+ const propagateJsClassicSearchParam = (reference, context) => {
48
+ const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
49
+ if (
50
+ !parentUrlInfo ||
51
+ !new URL(parentUrlInfo.url).searchParams.has("as_js_classic")
52
+ ) {
53
+ return null
54
+ }
55
+ const urlTransformed = injectQueryParams(reference.url, {
56
+ as_js_classic: "",
57
+ })
58
+ reference.filename = generateJsClassicFilename(reference.url)
59
+ return urlTransformed
60
+ }
61
+
62
+ return {
63
+ name: "jsenv:as_js_classic",
64
+ appliesDuring: "*",
65
+ // forward ?as_js_classic to referenced urls
66
+ redirectUrl: {
67
+ // We want to propagate transformation of js module to js classic to:
68
+ // - import specifier (static/dynamic import + re-export)
69
+ // - url specifier when inside System.register/_context.import()
70
+ // (because it's the transpiled equivalent of static and dynamic imports)
71
+ // And not other references otherwise we could try to transform inline ressources
72
+ // or specifiers inside new URL()...
73
+ js_import_export: propagateJsClassicSearchParam,
74
+ js_url_specifier: (reference, context) => {
75
+ if (
76
+ reference.subtype === "system_register_arg" ||
77
+ reference.subtype === "system_import_arg"
78
+ ) {
79
+ return propagateJsClassicSearchParam(reference, context)
80
+ }
81
+ return null
82
+ },
83
+ },
84
+ fetchUrlContent: async (urlInfo, context) => {
85
+ const originalUrlInfo = await fetchOriginalUrlInfo({
86
+ urlInfo,
87
+ context,
88
+ searchParam: "as_js_classic",
89
+ // override the expectedType to "js_module"
90
+ // because when there is ?as_js_classic it means the underlying ressource
91
+ // is a js_module
92
+ expectedType: "js_module",
93
+ })
94
+ if (!originalUrlInfo) {
95
+ return null
96
+ }
97
+ const isJsEntryPoint =
98
+ // in general html files are entry points
99
+ // but during build js can be sepcified as an entry point
100
+ // (meaning there is no html file where we can inject systemjs)
101
+ // in that case we need to inject systemjs in the js file
102
+ originalUrlInfo.data.isEntryPoint ||
103
+ // In thoose case we need to inject systemjs the worker js file
104
+ originalUrlInfo.data.isWebWorkerEntryPoint
105
+ // if it's an entry point without dependency (it does not use import)
106
+ // then we can use UMD, otherwise we have to use systemjs
107
+ // because it is imported by systemjs
108
+ const jsClassicFormat =
109
+ isJsEntryPoint && !originalUrlInfo.data.usesImport ? "umd" : "system"
110
+ const { content, sourcemap } = await convertJsModuleToJsClassic({
111
+ systemJsInjection,
112
+ systemJsClientFileUrl,
113
+ urlInfo: originalUrlInfo,
114
+ isJsEntryPoint,
115
+ jsClassicFormat,
116
+ })
117
+ urlInfo.data.jsClassicFormat = jsClassicFormat
118
+ return {
119
+ type: "js_classic",
120
+ contentType: "text/javascript",
121
+ content,
122
+ sourcemap,
123
+ }
124
+ },
125
+ }
126
+ }
127
+
128
+ const generateJsClassicFilename = (url) => {
129
+ const filename = urlToFilename(url)
130
+ let [basename, extension] = splitFileExtension(filename)
131
+ const { searchParams } = new URL(url)
132
+ if (
133
+ searchParams.has("as_json_module") ||
134
+ searchParams.has("as_css_module") ||
135
+ searchParams.has("as_text_module")
136
+ ) {
137
+ extension = ".js"
138
+ }
139
+ return `${basename}.es5${extension}`
140
+ }
141
+
142
+ const splitFileExtension = (filename) => {
143
+ const dotLastIndex = filename.lastIndexOf(".")
144
+ if (dotLastIndex === -1) {
145
+ return [filename, ""]
146
+ }
147
+ return [filename.slice(0, dotLastIndex), filename.slice(dotLastIndex)]
148
+ }
149
+
150
+ const convertJsModuleToJsClassic = async ({
151
+ systemJsInjection,
152
+ systemJsClientFileUrl,
153
+ urlInfo,
154
+ isJsEntryPoint,
155
+ jsClassicFormat,
156
+ }) => {
157
+ const { code, map } = await applyBabelPlugins({
158
+ babelPlugins: [
159
+ ...(jsClassicFormat === "system"
160
+ ? [
161
+ // propposal-dynamic-import required with systemjs for babel8:
162
+ // https://github.com/babel/babel/issues/10746
163
+ require("@babel/plugin-proposal-dynamic-import"),
164
+ [
165
+ requireBabelPlugin("babel-plugin-transform-async-to-promises"),
166
+ {
167
+ topLevelAwait: "return",
168
+ },
169
+ ],
170
+ require("@babel/plugin-transform-modules-systemjs"),
171
+ ]
172
+ : [
173
+ [
174
+ requireBabelPlugin("babel-plugin-transform-async-to-promises"),
175
+ {
176
+ topLevelAwait: "simple",
177
+ },
178
+ ],
179
+ babelPluginTransformImportMetaUrl,
180
+ require("@babel/plugin-transform-modules-umd"),
181
+ ]),
182
+ ],
183
+ urlInfo,
184
+ })
185
+ if (systemJsInjection && jsClassicFormat === "system" && isJsEntryPoint) {
186
+ const magicSource = createMagicSource(code)
187
+ const systemjsCode = readFileSync(systemJsClientFileUrl, { as: "string" })
188
+ magicSource.prepend(`${systemjsCode}\n\n`)
189
+ const { content, sourcemap } = magicSource.toContentAndSourcemap()
190
+ return {
191
+ content,
192
+ sourcemap: await composeTwoSourcemaps(map, sourcemap),
193
+ }
194
+ }
195
+ return {
196
+ content: code,
197
+ sourcemap: map,
198
+ }
199
+ }
@@ -0,0 +1,270 @@
1
+ import {
2
+ getHtmlNodeAttributeByName,
3
+ getHtmlNodeTextNode,
4
+ parseHtmlString,
5
+ removeHtmlNodeAttributeByName,
6
+ assignHtmlNodeAttributes,
7
+ stringifyHtmlAst,
8
+ visitHtmlAst,
9
+ htmlNodePosition,
10
+ setHtmlNodeGeneratedText,
11
+ injectScriptAsEarlyAsPossible,
12
+ createHtmlNode,
13
+ } from "@jsenv/utils/html_ast/html_ast.js"
14
+ import { generateInlineContentUrl } from "@jsenv/utils/urls/inline_content_url_generator.js"
15
+ import { injectQueryParamsIntoSpecifier } from "@jsenv/utils/urls/url_utils.js"
16
+
17
+ export const jsenvPluginScriptTypeModuleAsClassic = ({
18
+ systemJsInjection,
19
+ systemJsClientFileUrl,
20
+ generateJsClassicFilename,
21
+ }) => {
22
+ return {
23
+ name: "jsenv:script_type_module_as_classic",
24
+ appliesDuring: "*",
25
+ transformUrlContent: {
26
+ html: async (urlInfo, context) => {
27
+ if (
28
+ context.isSupportedOnCurrentClients("script_type_module") &&
29
+ context.isSupportedOnCurrentClients("import_dynamic")
30
+ ) {
31
+ return null
32
+ }
33
+ const htmlAst = parseHtmlString(urlInfo.content)
34
+ const preloadAsScriptNodes = []
35
+ const modulePreloadNodes = []
36
+ const moduleScriptNodes = []
37
+ const classicScriptNodes = []
38
+ const visitLinkNodes = (node) => {
39
+ if (node.nodeName !== "link") {
40
+ return
41
+ }
42
+ const relAttribute = getHtmlNodeAttributeByName(node, "rel")
43
+ const rel = relAttribute ? relAttribute.value : undefined
44
+ if (rel === "modulepreload") {
45
+ modulePreloadNodes.push(node)
46
+ return
47
+ }
48
+ if (rel === "preload") {
49
+ const asAttribute = getHtmlNodeAttributeByName(node, "as")
50
+ const as = asAttribute ? asAttribute.value : undefined
51
+ if (as === "script") {
52
+ preloadAsScriptNodes.push(node)
53
+ }
54
+ return
55
+ }
56
+ }
57
+ const visitScriptNodes = (node) => {
58
+ if (node.nodeName !== "script") {
59
+ return
60
+ }
61
+ const typeAttribute = getHtmlNodeAttributeByName(node, "type")
62
+ const type = typeAttribute ? typeAttribute.value : undefined
63
+ if (type === "module") {
64
+ moduleScriptNodes.push(node)
65
+ return
66
+ }
67
+ if (type === undefined || type === "text/javascript") {
68
+ classicScriptNodes.push(node)
69
+ return
70
+ }
71
+ }
72
+ visitHtmlAst(htmlAst, (node) => {
73
+ visitLinkNodes(node)
74
+ visitScriptNodes(node)
75
+ })
76
+
77
+ const classicScriptUrls = []
78
+ const moduleScriptUrls = []
79
+ classicScriptNodes.forEach((classicScriptNode) => {
80
+ const srcAttribute = getHtmlNodeAttributeByName(
81
+ classicScriptNode,
82
+ "src",
83
+ )
84
+ if (srcAttribute) {
85
+ const url = new URL(srcAttribute.value, urlInfo.url).href
86
+ classicScriptUrls.push(url)
87
+ }
88
+ })
89
+ moduleScriptNodes.forEach((moduleScriptNode) => {
90
+ const srcAttribute = getHtmlNodeAttributeByName(
91
+ moduleScriptNode,
92
+ "src",
93
+ )
94
+ if (srcAttribute) {
95
+ const url = new URL(srcAttribute.value, urlInfo.url).href
96
+ moduleScriptUrls.push(url)
97
+ }
98
+ })
99
+
100
+ const jsModuleUrls = []
101
+ const getReferenceAsJsClassic = async (
102
+ reference,
103
+ {
104
+ // we don't cook ressource hints
105
+ // because they might refer to ressource that will be modified during build
106
+ // It also means something else HAVE to reference that url in order to cook it
107
+ // so that the preload is deleted by "resync_ressource_hints.js" otherwise
108
+ cookIt = false,
109
+ } = {},
110
+ ) => {
111
+ const [newReference, newUrlInfo] = context.referenceUtils.update(
112
+ reference,
113
+ {
114
+ expectedType: "js_classic",
115
+ specifier: injectQueryParamsIntoSpecifier(reference.specifier, {
116
+ as_js_classic: "",
117
+ }),
118
+ filename: generateJsClassicFilename(reference.url),
119
+ },
120
+ )
121
+ const jsModuleUrl = newUrlInfo.url
122
+ if (!jsModuleUrls.includes(jsModuleUrl)) {
123
+ jsModuleUrls.push(newUrlInfo.url)
124
+ }
125
+ if (cookIt) {
126
+ // during dev it means js modules will be cooked before server sends the HTML
127
+ // it's ok because:
128
+ // - during dev script_type_module are supported (dev use a recent browser)
129
+ // - even if browser is not supported it still works it's jus a bit slower
130
+ // because it needs to decide if systemjs will be injected or not
131
+ await context.cook({
132
+ reference: newReference,
133
+ urlInfo: newUrlInfo,
134
+ })
135
+ }
136
+ return [newReference, newUrlInfo]
137
+ }
138
+ const actions = []
139
+ preloadAsScriptNodes.forEach((preloadAsScriptNode) => {
140
+ const hrefAttribute = getHtmlNodeAttributeByName(
141
+ preloadAsScriptNode,
142
+ "href",
143
+ )
144
+ const href = hrefAttribute.value
145
+ const url = new URL(href, urlInfo.url).href
146
+ const expectedScriptType = moduleScriptUrls.includes(url)
147
+ ? "module"
148
+ : "classic"
149
+ // keep in mind:
150
+ // when the url is not referenced by a <script type="module">
151
+ // we assume we want to preload "classic" but it might not be the case
152
+ // but it's unlikely to happen and people should use "modulepreload" in that case anyway
153
+ if (expectedScriptType === "module") {
154
+ actions.push(async () => {
155
+ const reference =
156
+ context.referenceUtils.findByGeneratedSpecifier(href)
157
+ const [newReference] = await getReferenceAsJsClassic(reference)
158
+ assignHtmlNodeAttributes(preloadAsScriptNode, {
159
+ href: newReference.generatedSpecifier,
160
+ })
161
+ removeHtmlNodeAttributeByName(preloadAsScriptNode, "crossorigin")
162
+ })
163
+ }
164
+ })
165
+ modulePreloadNodes.forEach((modulePreloadNode) => {
166
+ const hrefAttribute = getHtmlNodeAttributeByName(
167
+ modulePreloadNode,
168
+ "href",
169
+ )
170
+ const href = hrefAttribute.value
171
+ actions.push(async () => {
172
+ const reference =
173
+ context.referenceUtils.findByGeneratedSpecifier(href)
174
+ const [newReference] = await getReferenceAsJsClassic(reference)
175
+ assignHtmlNodeAttributes(modulePreloadNode, {
176
+ rel: "preload",
177
+ as: "script",
178
+ href: newReference.generatedSpecifier,
179
+ })
180
+ })
181
+ })
182
+ moduleScriptNodes.forEach((moduleScriptNode) => {
183
+ const srcAttribute = getHtmlNodeAttributeByName(
184
+ moduleScriptNode,
185
+ "src",
186
+ )
187
+ if (srcAttribute) {
188
+ actions.push(async () => {
189
+ const specifier = srcAttribute.value
190
+ const reference =
191
+ context.referenceUtils.findByGeneratedSpecifier(specifier)
192
+ const [newReference] = await getReferenceAsJsClassic(reference, {
193
+ cookIt: true,
194
+ })
195
+ removeHtmlNodeAttributeByName(moduleScriptNode, "type")
196
+ srcAttribute.value = newReference.generatedSpecifier
197
+ })
198
+ return
199
+ }
200
+ const textNode = getHtmlNodeTextNode(moduleScriptNode)
201
+ actions.push(async () => {
202
+ const { line, column, lineEnd, columnEnd, isOriginal } =
203
+ htmlNodePosition.readNodePosition(moduleScriptNode, {
204
+ preferOriginal: true,
205
+ })
206
+ let inlineScriptUrl = generateInlineContentUrl({
207
+ url: urlInfo.url,
208
+ extension: ".js",
209
+ line,
210
+ column,
211
+ lineEnd,
212
+ columnEnd,
213
+ })
214
+ const [inlineReference] = context.referenceUtils.foundInline({
215
+ node: moduleScriptNode,
216
+ type: "script_src",
217
+ expectedType: "js_module",
218
+ isOriginalPosition: isOriginal,
219
+ // we remove 1 to the line because imagine the following html:
220
+ // <script>console.log('ok')</script>
221
+ // -> content starts same line as <script>
222
+ specifierLine: line - 1,
223
+ specifierColumn: column,
224
+ specifier: inlineScriptUrl,
225
+ contentType: "application/javascript",
226
+ content: textNode.value,
227
+ })
228
+ const [, newUrlInfo] = await getReferenceAsJsClassic(
229
+ inlineReference,
230
+ { cookIt: true },
231
+ )
232
+ removeHtmlNodeAttributeByName(moduleScriptNode, "type")
233
+ setHtmlNodeGeneratedText(moduleScriptNode, {
234
+ generatedText: newUrlInfo.content,
235
+ generatedBy: "jsenv:script_type_module_as_classic",
236
+ })
237
+ })
238
+ })
239
+
240
+ if (actions.length === 0) {
241
+ return null
242
+ }
243
+ await Promise.all(actions.map((action) => action()))
244
+ if (systemJsInjection) {
245
+ const needsSystemJs = jsModuleUrls.some(
246
+ (jsModuleUrl) =>
247
+ context.urlGraph.getUrlInfo(jsModuleUrl).data.jsClassicFormat ===
248
+ "system",
249
+ )
250
+ if (needsSystemJs) {
251
+ const [systemJsReference] = context.referenceUtils.inject({
252
+ type: "script_src",
253
+ expectedType: "js_classic",
254
+ specifier: systemJsClientFileUrl,
255
+ })
256
+ injectScriptAsEarlyAsPossible(
257
+ htmlAst,
258
+ createHtmlNode({
259
+ "tagName": "script",
260
+ "src": systemJsReference.generatedSpecifier,
261
+ "injected-by": "jsenv:script_type_module_as_classic",
262
+ }),
263
+ )
264
+ }
265
+ }
266
+ return stringifyHtmlAst(htmlAst)
267
+ },
268
+ },
269
+ }
270
+ }
@@ -0,0 +1,55 @@
1
+ import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
2
+
3
+ export const jsenvPluginWorkersTypeModuleAsClassic = ({
4
+ generateJsClassicFilename,
5
+ }) => {
6
+ const updateReference = (reference) => {
7
+ reference.filename = generateJsClassicFilename(reference.url)
8
+ reference.mutation = (magicSource) => {
9
+ magicSource.replace({
10
+ start: reference.typePropertyNode.value.start,
11
+ end: reference.typePropertyNode.value.end,
12
+ replacement: JSON.stringify("classic"),
13
+ })
14
+ }
15
+ reference.expectedType = "js_classic"
16
+ return injectQueryParams(reference.url, {
17
+ as_js_classic: "",
18
+ })
19
+ }
20
+
21
+ return {
22
+ name: "jsenv:workers_type_module_as_classic",
23
+ appliesDuring: "*",
24
+ redirectUrl: {
25
+ js_url_specifier: (reference, context) => {
26
+ if (reference.expectedType !== "js_module") {
27
+ return null
28
+ }
29
+ if (reference.expectedSubtype === "worker") {
30
+ if (context.isSupportedOnCurrentClients("worker_type_module")) {
31
+ return null
32
+ }
33
+ return updateReference(reference)
34
+ }
35
+ if (reference.expectedSubtype === "service_worker") {
36
+ if (
37
+ context.isSupportedOnCurrentClients("service_worker_type_module")
38
+ ) {
39
+ return null
40
+ }
41
+ return updateReference(reference)
42
+ }
43
+ if (reference.expectedSubtype === "shared_worker") {
44
+ if (
45
+ context.isSupportedOnCurrentClients("shared_worker_type_module")
46
+ ) {
47
+ return null
48
+ }
49
+ return updateReference(reference)
50
+ }
51
+ return null
52
+ },
53
+ },
54
+ }
55
+ }
@@ -3,17 +3,12 @@ import { babelPluginCompatMap } from "./babel_plugins_compatibility.js"
3
3
 
4
4
  export const getBaseBabelPluginStructure = ({
5
5
  url,
6
- isSupportedOnRuntime,
7
- usesTopLevelAwait,
8
- // // https://github.com/rpetrich/babel-plugin-transform-async-to-promises/blob/92755ff8c943c97596523e586b5fa515c2e99326/async-to-promises.ts#L55
9
- topLevelAwait = "simple",
10
- isJsModule,
6
+ isSupported,
7
+ // isJsModule,
8
+ // getImportSpecifier,
11
9
  }) => {
12
10
  const isBabelPluginNeeded = (babelPluginName) => {
13
- return !isSupportedOnRuntime(
14
- babelPluginName,
15
- babelPluginCompatMap[babelPluginName],
16
- )
11
+ return !isSupported(babelPluginCompatMap[babelPluginName])
17
12
  }
18
13
 
19
14
  const babelPluginStructure = {}
@@ -40,21 +35,19 @@ export const getBaseBabelPluginStructure = ({
40
35
  babelPluginStructure["proposal-unicode-property-regex"] =
41
36
  requireBabelPlugin("@babel/plugin-proposal-unicode-property-regex")
42
37
  }
43
- if (
44
- isJsModule &&
45
- usesTopLevelAwait &&
46
- !isSupportedOnRuntime("top_level_await")
47
- ) {
38
+ if (isBabelPluginNeeded("transform-async-to-promises")) {
48
39
  babelPluginStructure["transform-async-to-promises"] = [
49
40
  requireBabelPlugin("babel-plugin-transform-async-to-promises"),
50
41
  {
51
- topLevelAwait,
42
+ topLevelAwait: "ignore", // will be handled by "jsenv:top_level_await" plugin
43
+ externalHelpers: false,
44
+ // enable once https://github.com/rpetrich/babel-plugin-transform-async-to-promises/pull/83
45
+ // externalHelpers: isJsModule,
46
+ // externalHelpersPath: isJsModule ? getImportSpecifier(
47
+ // "babel-plugin-transform-async-to-promises/helpers.mjs",
48
+ // ) : null
52
49
  },
53
50
  ]
54
- } else if (isBabelPluginNeeded("transform-async-to-promises")) {
55
- babelPluginStructure["transform-async-to-promises"] = requireBabelPlugin(
56
- "babel-plugin-transform-async-to-promises",
57
- )
58
51
  }
59
52
  if (isBabelPluginNeeded("transform-arrow-functions")) {
60
53
  babelPluginStructure["transform-arrow-functions"] = requireBabelPlugin(