@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
@@ -0,0 +1,105 @@
1
+ import { urlIsInsideOf } from "@jsenv/filesystem"
2
+
3
+ import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
4
+ import { parseHtmlString } from "@jsenv/utils/html_ast/html_ast.js"
5
+ import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
6
+ import { jsenvRootDirectoryUrl } from "@jsenv/core/src/jsenv_root_directory_url.js"
7
+ import { collectHotDataFromHtmlAst } from "./html_hot_dependencies.js"
8
+ import { babelPluginMetadataImportMetaHot } from "./babel_plugin_metadata_import_meta_hot.js"
9
+
10
+ export const jsenvPluginImportMetaHot = ({ rootDirectoryUrl }) => {
11
+ const preferSourceFiles =
12
+ rootDirectoryUrl === jsenvRootDirectoryUrl ||
13
+ urlIsInsideOf(rootDirectoryUrl, jsenvRootDirectoryUrl)
14
+ const importMetaHotClientFileUrl = preferSourceFiles
15
+ ? new URL("./client/import_meta_hot.js", import.meta.url).href
16
+ : new URL("./dist/import_meta_hot.js", jsenvRootDirectoryUrl).href
17
+
18
+ return {
19
+ name: "jsenv:import_meta_hot",
20
+ appliesDuring: "*",
21
+ transformUrlContent: {
22
+ html: (htmlUrlInfo, context) => {
23
+ // during build we don't really care to parse html hot dependencies
24
+ if (context.scenario === "build") {
25
+ return
26
+ }
27
+ const htmlAst = parseHtmlString(htmlUrlInfo.content)
28
+ const { hotReferences } = collectHotDataFromHtmlAst(htmlAst)
29
+ htmlUrlInfo.data.hotDecline = false
30
+ htmlUrlInfo.data.hotAcceptSelf = false
31
+ htmlUrlInfo.data.hotAcceptDependencies = hotReferences.map(
32
+ ({ type, specifier }) => {
33
+ const [reference] = context.referenceUtils.found({
34
+ type,
35
+ specifier,
36
+ })
37
+ return reference.url
38
+ },
39
+ )
40
+ },
41
+ css: (cssUrlInfo) => {
42
+ cssUrlInfo.data.hotDecline = false
43
+ cssUrlInfo.data.hotAcceptSelf = false
44
+ cssUrlInfo.data.hotAcceptDependencies = []
45
+ },
46
+ js_module: async (urlInfo, context) => {
47
+ if (!urlInfo.content.includes("import.meta.hot")) {
48
+ return null
49
+ }
50
+ const { metadata } = await applyBabelPlugins({
51
+ babelPlugins: [babelPluginMetadataImportMetaHot],
52
+ urlInfo,
53
+ })
54
+ const {
55
+ importMetaHotPaths,
56
+ hotDecline,
57
+ hotAcceptSelf,
58
+ hotAcceptDependencies,
59
+ } = metadata
60
+ urlInfo.data.hotDecline = hotDecline
61
+ urlInfo.data.hotAcceptSelf = hotAcceptSelf
62
+ urlInfo.data.hotAcceptDependencies = hotAcceptDependencies
63
+ if (importMetaHotPaths.length === 0) {
64
+ return null
65
+ }
66
+ if (context.scenario === "build") {
67
+ return removeImportMetaHots(urlInfo, importMetaHotPaths)
68
+ }
69
+ return injectImportMetaHot(urlInfo, context, importMetaHotClientFileUrl)
70
+ },
71
+ },
72
+ }
73
+ }
74
+
75
+ const removeImportMetaHots = (urlInfo, importMetaHotPaths) => {
76
+ const magicSource = createMagicSource(urlInfo.content)
77
+ importMetaHotPaths.forEach((path) => {
78
+ magicSource.replace({
79
+ start: path.node.start,
80
+ end: path.node.end,
81
+ replacement: "undefined",
82
+ })
83
+ })
84
+ return magicSource.toContentAndSourcemap()
85
+ }
86
+
87
+ // For some reason using magic source here produce
88
+ // better sourcemap than doing the equivalent with babel
89
+ // I suspect it's because I was doing injectAstAfterImport(programPath, ast.program.body[0])
90
+ // which is likely not well supported by babel
91
+ const injectImportMetaHot = (urlInfo, context, importMetaHotClientFileUrl) => {
92
+ const [importMetaHotClientFileReference] = context.referenceUtils.inject({
93
+ parentUrl: urlInfo.url,
94
+ type: "js_import_export",
95
+ expectedType: "js_module",
96
+ specifier: importMetaHotClientFileUrl,
97
+ })
98
+ const magicSource = createMagicSource(urlInfo.content)
99
+ magicSource.prepend(
100
+ `import { createImportMetaHot } from ${importMetaHotClientFileReference.generatedSpecifier}
101
+ import.meta.hot = createImportMetaHot(import.meta.url)
102
+ `,
103
+ )
104
+ return magicSource.toContentAndSourcemap()
105
+ }
@@ -12,18 +12,22 @@
12
12
  import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
13
13
  import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
14
14
 
15
- import { collectProgramImportMetas } from "@jsenv/utils/js_ast/program_import_metas.js"
16
-
17
15
  export const jsenvPluginImportMetaScenarios = () => {
18
16
  return {
19
17
  name: "jsenv:import_meta_scenario",
20
18
  appliesDuring: "*",
21
- transform: {
22
- js_module: async ({ url, content }, { scenario }) => {
19
+ transformUrlContent: {
20
+ js_module: async (urlInfo, { scenario }) => {
21
+ if (
22
+ !urlInfo.content.includes("import.meta.dev") &&
23
+ !urlInfo.content.includes("import.meta.test") &&
24
+ !urlInfo.content.includes("import.meta.build")
25
+ ) {
26
+ return null
27
+ }
23
28
  const { metadata } = await applyBabelPlugins({
24
29
  babelPlugins: [babelPluginMetadataImportMetaScenarios],
25
- url,
26
- content,
30
+ urlInfo,
27
31
  })
28
32
  const { dev = [], test = [], build = [] } = metadata.importMetaScenarios
29
33
  const replacements = []
@@ -59,7 +63,7 @@ export const jsenvPluginImportMetaScenarios = () => {
59
63
  replace(path, "true")
60
64
  })
61
65
  }
62
- const magicSource = createMagicSource(content)
66
+ const magicSource = createMagicSource(urlInfo.content)
63
67
  replacements.forEach(({ path, value }) => {
64
68
  magicSource.replace({
65
69
  start: path.node.start,
@@ -78,7 +82,28 @@ const babelPluginMetadataImportMetaScenarios = () => {
78
82
  name: "metadata-import-meta-scenarios",
79
83
  visitor: {
80
84
  Program(programPath, state) {
81
- const importMetas = collectProgramImportMetas(programPath)
85
+ const importMetas = {}
86
+ programPath.traverse({
87
+ MemberExpression(path) {
88
+ const { node } = path
89
+ const { object } = node
90
+ if (object.type !== "MetaProperty") {
91
+ return
92
+ }
93
+ const { property: objectProperty } = object
94
+ if (objectProperty.name !== "meta") {
95
+ return
96
+ }
97
+ const { property } = node
98
+ const { name } = property
99
+ const importMetaPaths = importMetas[name]
100
+ if (importMetaPaths) {
101
+ importMetaPaths.push(path)
102
+ } else {
103
+ importMetas[name] = [path]
104
+ }
105
+ },
106
+ })
82
107
  state.file.metadata.importMetaScenarios = {
83
108
  dev: importMetas.dev,
84
109
  test: importMetas.test,
@@ -0,0 +1,52 @@
1
+ const getCurrentScriptSrc = () => {
2
+ const { currentScript } = document
3
+ if (currentScript) return currentScript.src
4
+
5
+ // https://github.com/amiller-gh/currentScript-polyfill
6
+
7
+ const scripts = Array.prototype.slice.call(
8
+ document.getElementsByTagName("script"),
9
+ )
10
+
11
+ const readyScript = scripts.find((script) => {
12
+ return script.readyState === "interactive"
13
+ })
14
+ if (readyScript) return readyScript
15
+
16
+ try {
17
+ throw new Error()
18
+ } catch (err) {
19
+ // Find the second match for the "at" string to get file src url from stack.
20
+ // Specifically works with the format of stack traces in IE.
21
+ const stackDetails = /.*at [^(]*\((.*):(.+):(.+)\)$/gi.exec(err.stack)
22
+ const scriptLocation = (stackDetails || [false])[1]
23
+ const line = (stackDetails || [false])[2]
24
+ const currentLocation = document.location.href.replace(
25
+ document.location.hash,
26
+ "",
27
+ )
28
+
29
+ if (scriptLocation === currentLocation) {
30
+ const source = document.documentElement.outerHTML
31
+ const codeRegExp = new RegExp(
32
+ `(?:[^\\n]+?\\n){0,${
33
+ line - 2
34
+ }}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*`,
35
+ "i",
36
+ )
37
+ const code = source.replace(codeRegExp, "$1").trim()
38
+
39
+ return scripts.find((script) => {
40
+ return script.innerHTML && script.innerHTML.trim() === code
41
+ })
42
+ }
43
+
44
+ return scripts.find((script) => {
45
+ return script.src === scriptLocation
46
+ })
47
+ }
48
+ }
49
+
50
+ const url = getCurrentScriptSrc()
51
+
52
+ export default url
@@ -0,0 +1,9 @@
1
+ /* global __filename */
2
+
3
+ const filenameContainsBackSlashes = __filename.indexOf("\\") > -1
4
+
5
+ const url = filenameContainsBackSlashes
6
+ ? `file:///${__filename.replace(/\\/g, "/")}`
7
+ : `file://${__filename}`
8
+
9
+ export default url
@@ -30,8 +30,7 @@ import {
30
30
  getHtmlNodeAttributeByName,
31
31
  htmlNodePosition,
32
32
  removeHtmlNodeAttributeByName,
33
- setHtmlNodeText,
34
- assignHtmlNodeAttributes,
33
+ setHtmlNodeGeneratedText,
35
34
  getHtmlNodeTextNode,
36
35
  removeHtmlNode,
37
36
  } from "@jsenv/utils/html_ast/html_ast.js"
@@ -59,16 +58,16 @@ export const jsenvPluginImportmap = () => {
59
58
  return {
60
59
  name: "jsenv:importmap",
61
60
  appliesDuring: "*",
62
- resolve: {
63
- js_import_export: ({ parentUrl, specifier }) => {
61
+ resolveUrl: {
62
+ js_import_export: (reference) => {
64
63
  if (!finalImportmap) {
65
64
  return null
66
65
  }
67
66
  try {
68
67
  let fromMapping = false
69
68
  const result = resolveImport({
70
- specifier,
71
- importer: parentUrl,
69
+ specifier: reference.specifier,
70
+ importer: reference.parentUrl,
72
71
  importMap: finalImportmap,
73
72
  onImportMapping: () => {
74
73
  fromMapping = true
@@ -91,12 +90,9 @@ export const jsenvPluginImportmap = () => {
91
90
  }
92
91
  },
93
92
  },
94
- transform: {
95
- html: async (
96
- { url, content, references },
97
- { scenario, cook, urlGraph, referenceUtils },
98
- ) => {
99
- const htmlAst = parseHtmlString(content)
93
+ transformUrlContent: {
94
+ html: async (htmlUrlInfo, context) => {
95
+ const htmlAst = parseHtmlString(htmlUrlInfo.content)
100
96
  const importmap = findNode(htmlAst, (node) => {
101
97
  if (node.nodeName !== "script") {
102
98
  return false
@@ -108,7 +104,7 @@ export const jsenvPluginImportmap = () => {
108
104
  return true
109
105
  })
110
106
  if (!importmap) {
111
- onHtmlImportmapParsed(null, url)
107
+ onHtmlImportmapParsed(null, htmlUrlInfo.url)
112
108
  return null
113
109
  }
114
110
  const handleInlineImportmap = async (importmap, textNode) => {
@@ -117,7 +113,7 @@ export const jsenvPluginImportmap = () => {
117
113
  preferOriginal: true,
118
114
  })
119
115
  const inlineImportmapUrl = generateInlineContentUrl({
120
- url,
116
+ url: htmlUrlInfo.url,
121
117
  extension: ".importmap",
122
118
  line,
123
119
  column,
@@ -125,21 +121,27 @@ export const jsenvPluginImportmap = () => {
125
121
  columnEnd,
126
122
  })
127
123
  const [inlineImportmapReference, inlineImportmapUrlInfo] =
128
- referenceUtils.foundInline({
124
+ context.referenceUtils.foundInline({
129
125
  type: "script_src",
130
- line: line - 1,
131
- column,
132
- isOriginal,
126
+ isOriginalPosition: isOriginal,
127
+ specifierLine: line - 1,
128
+ specifierColumn: column,
133
129
  specifier: inlineImportmapUrl,
134
130
  contentType: "application/importmap+json",
135
131
  content: textNode.value,
136
132
  })
137
- await cook({
133
+ await context.cook({
138
134
  reference: inlineImportmapReference,
139
135
  urlInfo: inlineImportmapUrlInfo,
140
136
  })
141
- setHtmlNodeText(importmap, inlineImportmapUrlInfo.content)
142
- onHtmlImportmapParsed(JSON.parse(inlineImportmapUrlInfo.content), url)
137
+ setHtmlNodeGeneratedText(importmap, {
138
+ generatedText: inlineImportmapUrlInfo.content,
139
+ generatedBy: "jsenv:importmap",
140
+ })
141
+ onHtmlImportmapParsed(
142
+ JSON.parse(inlineImportmapUrlInfo.content),
143
+ htmlUrlInfo.url,
144
+ )
143
145
  }
144
146
  const handleImportmapWithSrc = async (importmap, src) => {
145
147
  // Browser would throw on remote importmap
@@ -147,35 +149,39 @@ export const jsenvPluginImportmap = () => {
147
149
  // We must precook the importmap to know its content and inline it into the HTML
148
150
  // In this situation the ref to the importmap was already discovered
149
151
  // when parsing the HTML
150
- const importmapReference = references.find(
151
- (reference) => reference.url === src,
152
+ const importmapReference =
153
+ context.referenceUtils.findByGeneratedSpecifier(src)
154
+ const importmapUrlInfo = context.urlGraph.getUrlInfo(
155
+ importmapReference.url,
152
156
  )
153
- const importmapUrlInfo = urlGraph.getUrlInfo(importmapReference.url)
154
- await cook({
157
+ await context.cook({
155
158
  reference: importmapReference,
156
159
  urlInfo: importmapUrlInfo,
157
160
  })
158
- onHtmlImportmapParsed(JSON.parse(importmapUrlInfo.content), url)
161
+ onHtmlImportmapParsed(
162
+ JSON.parse(importmapUrlInfo.content),
163
+ htmlUrlInfo.url,
164
+ )
159
165
  removeHtmlNodeAttributeByName(importmap, "src")
160
- assignHtmlNodeAttributes(importmap, {
161
- "content-src": src,
162
- "inlined-by": "jsenv:importmap",
166
+ setHtmlNodeGeneratedText(importmap, {
167
+ generatedText: importmapUrlInfo.content,
168
+ generatedBy: "jsenv:importmap",
169
+ generatedFromSrc: src,
163
170
  })
164
- setHtmlNodeText(importmap, importmapUrlInfo.content)
165
171
 
166
172
  const { line, column, lineEnd, columnEnd, isOriginal } =
167
173
  htmlNodePosition.readNodePosition(importmap, {
168
174
  preferOriginal: true,
169
175
  })
170
176
  const inlineImportmapUrl = generateInlineContentUrl({
171
- url,
177
+ url: htmlUrlInfo.url,
172
178
  extension: ".importmap",
173
179
  line,
174
180
  column,
175
181
  lineEnd,
176
182
  columnEnd,
177
183
  })
178
- referenceUtils.becomesInline(importmapReference, {
184
+ context.referenceUtils.becomesInline(importmapReference, {
179
185
  line: line - 1,
180
186
  column,
181
187
  isOriginal,
@@ -200,7 +206,7 @@ export const jsenvPluginImportmap = () => {
200
206
  // by "formatReferencedUrl" making the importmap presence useless.
201
207
  // In dev/test we keep importmap into the HTML to see it even if useless
202
208
  // Duing build we get rid of it
203
- if (scenario === "build") {
209
+ if (context.scenario === "build") {
204
210
  removeHtmlNode(importmap)
205
211
  }
206
212
  return {
@@ -0,0 +1,67 @@
1
+ import {
2
+ parseHtmlString,
3
+ injectScriptAsEarlyAsPossible,
4
+ createHtmlNode,
5
+ stringifyHtmlAst,
6
+ } from "@jsenv/utils/html_ast/html_ast.js"
7
+ import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
8
+ import { isWebWorkerUrlInfo } from "@jsenv/core/src/omega/web_workers.js"
9
+
10
+ export const jsenvPluginInjectGlobals = (globals = {}) => {
11
+ if (Object.keys(globals).length === 0) {
12
+ return []
13
+ }
14
+
15
+ const globalInjectorOnHtmlEntryPoint = (urlInfo) => {
16
+ if (!urlInfo.data.isEntryPoint) {
17
+ return null
18
+ }
19
+ // ideally we would inject an importmap but browser support is too low
20
+ // (even worse for worker/service worker)
21
+ // so for now we inject code into entry points
22
+ const htmlAst = parseHtmlString(urlInfo.content, {
23
+ storeOriginalPositions: false,
24
+ })
25
+ injectScriptAsEarlyAsPossible(
26
+ htmlAst,
27
+ createHtmlNode({
28
+ "tagName": "script",
29
+ "textContent": generateClientCodeForGlobals({
30
+ globals,
31
+ isWebWorker: false,
32
+ }),
33
+ "injected-by": "jsenv:inject_globals",
34
+ }),
35
+ )
36
+ return stringifyHtmlAst(htmlAst)
37
+ }
38
+
39
+ const globalsInjectorOnJsEntryPoints = (urlInfo) => {
40
+ if (!urlInfo.data.isEntryPoint && !urlInfo.data.isWebWorkerEntryPoint) {
41
+ return null
42
+ }
43
+ const magicSource = createMagicSource(urlInfo.content)
44
+ magicSource.append(
45
+ generateClientCodeForGlobals({
46
+ globals,
47
+ isWebWorker: isWebWorkerUrlInfo(urlInfo),
48
+ }),
49
+ )
50
+ return magicSource.toContentAndSourcemap()
51
+ }
52
+
53
+ return {
54
+ name: "jsenv:inject_globals",
55
+ appliesDuring: "*",
56
+ transformUrlContent: {
57
+ html: globalInjectorOnHtmlEntryPoint,
58
+ js_classic: globalsInjectorOnJsEntryPoints,
59
+ js_module: globalsInjectorOnJsEntryPoints,
60
+ },
61
+ }
62
+ }
63
+
64
+ const generateClientCodeForGlobals = ({ isWebWorker = false, globals }) => {
65
+ const globalName = isWebWorker ? "self" : "window"
66
+ return `Object.assign(${globalName}, ${JSON.stringify(globals, null, " ")});`
67
+ }
@@ -1,42 +1,46 @@
1
1
  import { DataUrl } from "@jsenv/utils/urls/data_url.js"
2
- import { ContentType } from "@jsenv/utils/src/content_type.js"
2
+ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
3
3
 
4
4
  export const jsenvPluginDataUrls = () => {
5
5
  return {
6
6
  name: "jsenv:data_urls",
7
7
  appliesDuring: "*",
8
- resolve: ({ specifier }) => {
9
- if (!specifier.startsWith("data:")) {
8
+ resolveUrl: (reference) => {
9
+ if (!reference.specifier.startsWith("data:")) {
10
10
  return null
11
11
  }
12
- return specifier
12
+ return reference.specifier
13
13
  },
14
- load: ({ url, data }) => {
15
- if (!url.startsWith("data:")) {
14
+ fetchUrlContent: (urlInfo) => {
15
+ if (!urlInfo.url.startsWith("data:")) {
16
16
  return null
17
17
  }
18
- const { contentType, base64Flag, data: urlData } = DataUrl.parse(url)
19
- data.base64Flag = base64Flag
18
+ const {
19
+ contentType,
20
+ base64Flag,
21
+ data: urlData,
22
+ } = DataUrl.parse(urlInfo.url)
23
+ urlInfo.data.base64Flag = base64Flag
20
24
  return {
21
25
  contentType,
22
26
  content: contentFromUrlData({ contentType, base64Flag, urlData }),
23
27
  }
24
28
  },
25
- formatReferencedUrl: (reference, { urlGraph, cook }) => {
26
- if (!reference.url.startsWith("data:")) {
29
+ formatUrl: (reference, context) => {
30
+ if (!reference.generatedUrl.startsWith("data:")) {
27
31
  return null
28
32
  }
29
33
  if (reference.type === "sourcemap_comment") {
30
34
  return null
31
35
  }
32
36
  return (async () => {
33
- const urlInfo = urlGraph.getUrlInfo(reference.url)
34
- await cook({
37
+ const urlInfo = context.urlGraph.getUrlInfo(reference.url)
38
+ await context.cook({
35
39
  reference,
36
40
  urlInfo,
37
41
  })
38
42
  if (urlInfo.originalContent === urlInfo.content) {
39
- return reference.url
43
+ return reference.generatedUrl
40
44
  }
41
45
  const specifier = DataUrl.stringify({
42
46
  contentType: urlInfo.contentType,
@@ -52,7 +56,7 @@ export const jsenvPluginDataUrls = () => {
52
56
  }
53
57
 
54
58
  const contentFromUrlData = ({ contentType, base64Flag, urlData }) => {
55
- if (ContentType.isTextual(contentType)) {
59
+ if (CONTENT_TYPE.isTextual(contentType)) {
56
60
  if (base64Flag) {
57
61
  return base64ToString(urlData)
58
62
  }