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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/event_source_client.js +549 -0
  2. package/dist/event_source_client.js.map +188 -0
  3. package/dist/html_supervisor_installer.js +1145 -0
  4. package/dist/html_supervisor_installer.js.map +322 -0
  5. package/dist/html_supervisor_setup.js +92 -0
  6. package/dist/html_supervisor_setup.js.map +57 -0
  7. package/main.js +8 -1
  8. package/package.json +22 -21
  9. package/readme.md +4 -12
  10. package/src/build/build.js +731 -433
  11. package/src/build/build_urls_generator.js +55 -21
  12. package/src/build/graph_utils.js +31 -0
  13. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  14. package/src/build/inject_service_worker_urls.js +79 -0
  15. package/src/build/resync_ressource_hints.js +68 -0
  16. package/src/build/start_build_server.js +205 -0
  17. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  18. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  19. package/src/dev/start_dev_server.js +58 -26
  20. package/src/execute/execute.js +30 -4
  21. package/src/execute/run.js +19 -56
  22. package/src/execute/runtimes/browsers/from_playwright.js +201 -147
  23. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  24. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  25. package/src/execute/runtimes/node/node_process.js +280 -39
  26. package/src/jsenv_root_directory_url.js +1 -0
  27. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  28. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  29. package/src/omega/compat/runtime_compat.js +50 -0
  30. package/src/omega/errors.js +51 -58
  31. package/src/omega/fetched_content_compliance.js +24 -0
  32. package/src/omega/file_url_converter.js +8 -50
  33. package/src/omega/kitchen.js +414 -285
  34. package/src/omega/server/file_service.js +21 -22
  35. package/src/omega/url_graph/url_graph_load.js +14 -7
  36. package/src/omega/url_graph/url_graph_report.js +17 -15
  37. package/src/omega/url_graph/url_info_transformations.js +17 -5
  38. package/src/omega/url_graph.js +33 -10
  39. package/src/omega/web_workers.js +42 -0
  40. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  41. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  42. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  43. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  44. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
  45. package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +31 -172
  46. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
  47. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  48. package/src/plugins/bundling/css/bundle_css.js +21 -0
  49. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  50. package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +120 -79
  51. package/src/plugins/bundling/jsenv_plugin_bundling.js +51 -0
  52. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
  53. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  54. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
  55. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  56. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  57. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_installer.js +3 -2
  58. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_setup.js +0 -0
  59. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  60. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  61. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +52 -55
  62. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  63. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  64. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  65. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  66. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +101 -0
  67. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
  68. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  69. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  70. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +37 -31
  71. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
  72. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  73. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  74. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +61 -40
  75. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  76. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  77. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
  78. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  79. package/src/plugins/minification/css/minify_css.js +9 -0
  80. package/src/plugins/minification/html/minify_html.js +15 -0
  81. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  82. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  83. package/src/plugins/minification/json/minify_json.js +8 -0
  84. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
  85. package/src/{omega → plugins}/plugin_controller.js +39 -11
  86. package/src/plugins/plugins.js +89 -0
  87. package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
  88. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  89. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  90. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  91. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
  92. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
  93. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +93 -0
  94. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  95. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  96. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
  97. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
  98. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
  100. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  101. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  102. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  103. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  104. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  105. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  106. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  107. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +200 -0
  108. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
  109. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  110. package/src/plugins/url_references/css/css_urls.js +49 -0
  111. package/src/plugins/url_references/html/html_urls.js +273 -0
  112. package/src/plugins/url_references/js/js_urls.js +43 -0
  113. package/src/plugins/url_references/jsenv_plugin_imports_analysis.js +46 -0
  114. package/src/plugins/url_references/jsenv_plugin_url_analysis.js +18 -0
  115. package/src/plugins/url_references/jsenv_plugin_url_references.js +6 -0
  116. package/src/plugins/url_references/webmanifest/webmanifest_urls.js +17 -0
  117. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  118. package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
  119. package/src/test/execute_plan.js +28 -11
  120. package/src/test/execute_test_plan.js +23 -8
  121. package/src/test/logs_file_execution.js +8 -7
  122. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  123. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  124. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  125. package/src/execute/runtimes/node/controlled_process.js +0 -316
  126. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  127. package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
  128. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  129. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  130. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  131. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  132. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  133. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  134. package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
  135. package/src/omega/core_plugins.js +0 -39
  136. package/src/omega/runtime_support/runtime_support.js +0 -20
  137. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  138. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  139. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  140. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  141. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -42,15 +42,11 @@ export const createFileService = ({
42
42
  const { runtimeName, runtimeVersion } = parseUserAgentHeader(
43
43
  request.headers["user-agent"],
44
44
  )
45
- const runtimeSupport = {
46
- [runtimeName]: runtimeVersion,
47
- }
48
- const reference = kitchen.createReference({
45
+ const [reference, urlInfo] = kitchen.prepareEntryPoint({
49
46
  parentUrl: inferParentFromRequest(request, rootDirectoryUrl),
50
47
  type: "entry_point",
51
48
  specifier: request.ressource,
52
49
  })
53
- const requestedUrlInfo = kitchen.resolveReference(reference)
54
50
  const referenceFromGraph = urlGraph.inferReference(
55
51
  reference.url,
56
52
  reference.parentUrl,
@@ -58,15 +54,17 @@ export const createFileService = ({
58
54
  try {
59
55
  await kitchen.cook({
60
56
  reference: referenceFromGraph || reference,
61
- urlInfo: requestedUrlInfo,
57
+ urlInfo,
62
58
  outDirectoryUrl: `${rootDirectoryUrl}.jsenv/${scenario}/${runtimeName}@${runtimeVersion}/`,
63
- runtimeSupport,
59
+ clientRuntimeCompat: {
60
+ [runtimeName]: runtimeVersion,
61
+ },
64
62
  })
65
- const { response, contentType, content } = requestedUrlInfo
63
+ let { response, contentType, content } = urlInfo
66
64
  if (response) {
67
65
  return response
68
66
  }
69
- return {
67
+ response = {
70
68
  url: reference.url,
71
69
  status: 200,
72
70
  headers: {
@@ -75,7 +73,17 @@ export const createFileService = ({
75
73
  "cache-control": `private,max-age=0,must-revalidate`,
76
74
  },
77
75
  body: content,
76
+ timing: urlInfo.timing,
78
77
  }
78
+ kitchen.pluginController.callHooks(
79
+ "augmentResponse",
80
+ { reference, urlInfo },
81
+ {},
82
+ (returnValue) => {
83
+ response = composeTwoResponses(response, returnValue)
84
+ },
85
+ )
86
+ return response
79
87
  } catch (e) {
80
88
  const code = e.code
81
89
  if (code === "PARSE_ERROR") {
@@ -86,11 +94,11 @@ export const createFileService = ({
86
94
  statusText: e.reason,
87
95
  statusMessage: e.message,
88
96
  headers: {
89
- "content-type": requestedUrlInfo.contentType,
90
- "content-length": Buffer.byteLength(requestedUrlInfo.content),
97
+ "content-type": urlInfo.contentType,
98
+ "content-length": Buffer.byteLength(urlInfo.content),
91
99
  "cache-control": "no-store",
92
100
  },
93
- body: requestedUrlInfo.content,
101
+ body: urlInfo.content,
94
102
  }
95
103
  }
96
104
  if (code === "EISDIR") {
@@ -127,16 +135,7 @@ export const createFileService = ({
127
135
  }
128
136
  return async (request) => {
129
137
  let response = await getResponse(request)
130
- if (response.url) {
131
- kitchen.pluginController.callHooks(
132
- "augmentResponse",
133
- response,
134
- {},
135
- (returnValue) => {
136
- response = composeTwoResponses(response, returnValue)
137
- },
138
- )
139
- }
138
+
140
139
  return response
141
140
  }
142
141
  }
@@ -5,23 +5,24 @@ export const loadUrlGraph = async ({
5
5
  kitchen,
6
6
  startLoading,
7
7
  outDirectoryUrl,
8
- runtimeSupport,
8
+ clientRuntimeCompat,
9
9
  }) => {
10
10
  if (outDirectoryUrl) {
11
11
  await ensureEmptyDirectory(outDirectoryUrl)
12
12
  }
13
13
  const promises = []
14
+ const promiseMap = new Map()
14
15
  const cook = ({ urlInfo, ...rest }) => {
15
- const promiseFromData = urlInfo.data.promise
16
+ const promiseFromData = promiseMap.get(urlInfo)
16
17
  if (promiseFromData) return promiseFromData
17
18
  const promise = _cook({
18
19
  urlInfo,
19
20
  outDirectoryUrl,
20
- runtimeSupport,
21
+ clientRuntimeCompat,
21
22
  ...rest,
22
23
  })
23
24
  promises.push(promise)
24
- urlInfo.data.promise = promise
25
+ promiseMap.set(urlInfo, promise)
25
26
  return promise
26
27
  }
27
28
  const _cook = async ({ urlInfo, ...rest }) => {
@@ -32,26 +33,31 @@ export const loadUrlGraph = async ({
32
33
  })
33
34
  const { references } = urlInfo
34
35
  references.forEach((reference) => {
36
+ // we use reference.generatedUrl to mimic what a browser would do:
37
+ // do a fetch to the specifier as found in the file
38
+ const referencedUrlInfo = urlGraph.reuseOrCreateUrlInfo(
39
+ reference.generatedUrl,
40
+ )
35
41
  cook({
36
42
  reference,
37
- urlInfo: urlGraph.getUrlInfo(reference.url),
43
+ urlInfo: referencedUrlInfo,
38
44
  })
39
45
  })
40
46
  }
41
47
  startLoading(
42
48
  ({ trace, parentUrl = kitchen.rootDirectoryUrl, type, specifier }) => {
43
- const entryReference = kitchen.createReference({
49
+ const [entryReference, entryUrlInfo] = kitchen.prepareEntryPoint({
44
50
  trace,
45
51
  parentUrl,
46
52
  type,
47
53
  specifier,
48
54
  })
49
- const entryUrlInfo = kitchen.resolveReference(entryReference)
50
55
  entryUrlInfo.data.isEntryPoint = true
51
56
  cook({
52
57
  reference: entryReference,
53
58
  urlInfo: entryUrlInfo,
54
59
  })
60
+ return [entryReference, entryUrlInfo]
55
61
  },
56
62
  )
57
63
 
@@ -65,4 +71,5 @@ export const loadUrlGraph = async ({
65
71
  await waitAll()
66
72
  }
67
73
  await waitAll()
74
+ promiseMap.clear()
68
75
  }
@@ -22,7 +22,7 @@ const createUrlGraphReport = (urlGraph) => {
22
22
  html: 0,
23
23
  css: 0,
24
24
  js: 0,
25
- assets: 0,
25
+ other: 0,
26
26
  sourcemaps: 0,
27
27
  total: 0,
28
28
  }
@@ -31,7 +31,7 @@ const createUrlGraphReport = (urlGraph) => {
31
31
  css: 0,
32
32
  js: 0,
33
33
  sourcemaps: 0,
34
- assets: 0,
34
+ other: 0,
35
35
  total: 0,
36
36
  }
37
37
  Object.keys(urlInfos).forEach((url) => {
@@ -39,8 +39,10 @@ const createUrlGraphReport = (urlGraph) => {
39
39
  return
40
40
  }
41
41
  const urlInfo = urlInfos[url]
42
- // ignore inline files, they are already taken into account in the file where they appear
43
- if (urlInfo.isInline) {
42
+ // ignore:
43
+ // - inline files: they are already taken into account in the file where they appear
44
+ // - external files: we don't know their content
45
+ if (urlInfo.isInline || urlInfo.external) {
44
46
  return
45
47
  }
46
48
  // file loaded via import assertion are already inside the graph
@@ -49,9 +51,9 @@ const createUrlGraphReport = (urlGraph) => {
49
51
  // and only the js module remain (likely bundled)
50
52
  const urlObject = new URL(urlInfo.url)
51
53
  if (
52
- urlObject.searchParams.has("json_module") ||
53
- urlObject.searchParams.has("css_module") ||
54
- urlObject.searchParams.has("text_module")
54
+ urlObject.searchParams.has("as_json_module") ||
55
+ urlObject.searchParams.has("as_css_module") ||
56
+ urlObject.searchParams.has("as_text_module")
55
57
  ) {
56
58
  return
57
59
  }
@@ -79,8 +81,8 @@ const createUrlGraphReport = (urlGraph) => {
79
81
  sizeGroups.js += urlContentSize
80
82
  return
81
83
  }
82
- countGroups.assets++
83
- sizeGroups.assets += urlContentSize
84
+ countGroups.other++
85
+ sizeGroups.other += urlContentSize
84
86
  return
85
87
  })
86
88
  return {
@@ -88,7 +90,7 @@ const createUrlGraphReport = (urlGraph) => {
88
90
  css: { count: countGroups.css, size: sizeGroups.css },
89
91
  js: { count: countGroups.js, size: sizeGroups.js },
90
92
  sourcemaps: { count: countGroups.sourcemaps, size: sizeGroups.sourcemaps },
91
- assets: { count: countGroups.assets, size: sizeGroups.assets },
93
+ other: { count: countGroups.other, size: sizeGroups.other },
92
94
  total: { count: countGroups.total, size: sizeGroups.total },
93
95
  }
94
96
  }
@@ -106,10 +108,10 @@ const determineCategory = (urlInfo) => {
106
108
  if (urlInfo.type === "js_module" || urlInfo.type === "js_classic") {
107
109
  return "js"
108
110
  }
109
- return "assets"
111
+ return "other"
110
112
  }
111
113
 
112
- const createRepartitionMessage = ({ html, css, js, assets }) => {
114
+ const createRepartitionMessage = ({ html, css, js, other }) => {
113
115
  const parts = []
114
116
  if (html.count) {
115
117
  parts.push(
@@ -139,10 +141,10 @@ const createRepartitionMessage = ({ html, css, js, assets }) => {
139
141
  // } (${byteAsFileSize(sourcemaps.size)})`,
140
142
  // )
141
143
  // }
142
- if (assets.count) {
144
+ if (other.count) {
143
145
  parts.push(
144
- `${ANSI.color(`assets:`, ANSI.GREY)} ${assets.count} (${byteAsFileSize(
145
- assets.size,
146
+ `${ANSI.color(`other:`, ANSI.GREY)} ${other.count} (${byteAsFileSize(
147
+ other.size,
146
148
  )})`,
147
149
  )
148
150
  }
@@ -1,3 +1,4 @@
1
+ import { urlToRelativeUrl } from "@jsenv/filesystem"
1
2
  import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_composition_v3.js"
2
3
  import {
3
4
  SOURCEMAP,
@@ -9,6 +10,7 @@ export const createUrlInfoTransformer = ({
9
10
  logger,
10
11
  sourcemaps,
11
12
  sourcemapsSources,
13
+ sourcemapsRelativeSources,
12
14
  urlGraph,
13
15
  injectSourcemapPlaceholder,
14
16
  foundSourcemap,
@@ -23,7 +25,12 @@ export const createUrlInfoTransformer = ({
23
25
  // for inline content (<script> insdide html)
24
26
  // chrome won't be able to fetch the file as it does not exists
25
27
  // so sourcemap must contain sources
26
- urlInfo.isInline || sourcemapsSources
28
+ sourcemapsSources ||
29
+ urlInfo.isInline ||
30
+ (sourcemap.sources &&
31
+ sourcemap.sources.some(
32
+ (source) => !source || !source.startsWith("file:"),
33
+ ))
27
34
  if (sourcemap.sources && sourcemap.sources.length > 1) {
28
35
  sourcemap.sources = sourcemap.sources.map(
29
36
  (source) => new URL(source, urlInfo.data.rawUrl || urlInfo.url).href,
@@ -137,11 +144,16 @@ export const createUrlInfoTransformer = ({
137
144
  const sourcemapReference = urlInfo.sourcemapReference
138
145
  const sourcemapUrlInfo = urlGraph.getUrlInfo(sourcemapReference.url)
139
146
  sourcemapUrlInfo.contentType = "application/json"
140
- sourcemapUrlInfo.content = JSON.stringify(urlInfo.sourcemap, null, " ")
147
+ const sourcemap = urlInfo.sourcemap
148
+ if (sourcemapsRelativeSources) {
149
+ sourcemap.sources = sourcemap.sources.map((source) => {
150
+ const sourceRelative = urlToRelativeUrl(source, urlInfo.url)
151
+ return sourceRelative
152
+ })
153
+ }
154
+ sourcemapUrlInfo.content = JSON.stringify(sourcemap, null, " ")
141
155
  if (sourcemaps === "inline") {
142
- sourcemapReference.generatedSpecifier = sourcemapToBase64Url(
143
- urlInfo.sourcemap,
144
- )
156
+ sourcemapReference.generatedSpecifier = sourcemapToBase64Url(sourcemap)
145
157
  }
146
158
  if (sourcemaps === "file" || sourcemaps === "inline") {
147
159
  urlInfo.content = SOURCEMAP.writeComment({
@@ -4,7 +4,16 @@ import { urlToRelativeUrl } from "@jsenv/filesystem"
4
4
  export const createUrlGraph = () => {
5
5
  const urlInfos = {}
6
6
  const getUrlInfo = (url) => urlInfos[url]
7
- const deleteUrlInfo = (url) => delete urlInfos[url]
7
+ const deleteUrlInfo = (url) => {
8
+ const urlInfo = urlInfos[url]
9
+ if (urlInfo) {
10
+ delete urlInfos[url]
11
+ if (urlInfo.sourcemapReference) {
12
+ deleteUrlInfo(urlInfo.sourcemapReference.url)
13
+ }
14
+ }
15
+ }
16
+
8
17
  const reuseOrCreateUrlInfo = (url) => {
9
18
  const existingUrlInfo = urlInfos[url]
10
19
  if (existingUrlInfo) return existingUrlInfo
@@ -44,9 +53,19 @@ export const createUrlGraph = () => {
44
53
  const updateReferences = (urlInfo, references) => {
45
54
  const dependencyUrls = []
46
55
  references.forEach((reference) => {
47
- if (!dependencyUrls.includes(reference.url)) {
48
- dependencyUrls.push(reference.url)
56
+ if (reference.isRessourceHint) {
57
+ // ressource hint are a special kind of reference.
58
+ // They are a sort of weak reference to an url.
59
+ // We ignore them so that url referenced only by ressource hints
60
+ // have url.dependents.size === 0 and can be considered as not used
61
+ // It means html won't consider url referenced solely
62
+ // by <link> as dependency and it's fine
63
+ return
64
+ }
65
+ if (dependencyUrls.includes(reference.url)) {
66
+ return
49
67
  }
68
+ dependencyUrls.push(reference.url)
50
69
  })
51
70
  pruneDependencies(
52
71
  urlInfo,
@@ -115,18 +134,22 @@ export const createUrlGraph = () => {
115
134
  const createUrlInfo = (url) => {
116
135
  return {
117
136
  data: {}, // plugins can put whatever they want here
137
+ references: [],
138
+ dependencies: new Set(),
139
+ dependents: new Set(),
140
+ type: undefined, // "html", "css", "js_classic", "js_module", "importmap", "json", "webmanifest", ...
141
+ subtype: undefined, // "worker", "service_worker", "shared_worker" for js, otherwise undefined
142
+ contentType: "", // "text/html", "text/css", "text/javascript", "application/json", ...
118
143
  url,
144
+ filename: "",
119
145
  generatedUrl: null,
120
146
  isInline: false,
121
147
  inlineUrlSite: null,
122
- contentType: "",
123
- originalContent: "",
124
- content: "",
148
+ external: false,
149
+ originalContent: undefined,
150
+ content: undefined,
125
151
  sourcemap: null,
126
152
  sourcemapReference: null,
127
- type: "",
128
- references: [],
129
- dependencies: new Set(),
130
- dependents: new Set(),
153
+ timing: {},
131
154
  }
132
155
  }
@@ -0,0 +1,42 @@
1
+ // the following apis are creating js entry points:
2
+ // - new Worker()
3
+ // - new SharedWorker()
4
+ // - navigator.serviceWorker.register()
5
+ export const isWebWorkerEntryPointReference = (reference) => {
6
+ if (reference.subtype === "new_url_first_arg") {
7
+ return ["worker", "service_worker", "shared_worker"].includes(
8
+ reference.expectedSubtype,
9
+ )
10
+ }
11
+ return [
12
+ "new_worker_first_arg",
13
+ "new_shared_worker_first_arg",
14
+ "service_worker_register_first_arg",
15
+ ].includes(reference.subtype)
16
+ }
17
+
18
+ export const isWebWorkerUrlInfo = (urlInfo) => {
19
+ return (
20
+ urlInfo.subtype === "worker" ||
21
+ urlInfo.subtype === "service_worker" ||
22
+ urlInfo.subtype === "shared_worker"
23
+ )
24
+ }
25
+
26
+ // export const isEntryPoint = (urlInfo, urlGraph) => {
27
+ // if (urlInfo.data.isEntryPoint) {
28
+ // return true
29
+ // }
30
+ // if (isWebWorker(urlInfo)) {
31
+ // // - new Worker("a.js") -> "a.js" is an entry point
32
+ // // - self.importScripts("b.js") -> "b.js" is not an entry point
33
+ // // So the following logic applies to infer if the file is a web worker entry point
34
+ // // "When a non-webworker file references a worker file, the worker file is an entry point"
35
+ // const dependents = Array.from(urlInfo.dependents)
36
+ // return dependents.some((dependentUrl) => {
37
+ // const dependentUrlInfo = urlGraph.getUrlInfo(dependentUrl)
38
+ // return !isWebWorker(dependentUrlInfo)
39
+ // })
40
+ // }
41
+ // return false
42
+ // }
@@ -1,4 +1,5 @@
1
- import { createEventSourceConnection } from "./event_source_connection.js"
1
+ import { createEventSourceConnection } from "@jsenv/utils/event_source/event_source.js"
2
+ import { urlHotMetas } from "../../../import_meta_hot/client/import_meta_hot.js"
2
3
  import {
3
4
  isAutoreloadEnabled,
4
5
  setAutoreloadPreference,
@@ -9,7 +10,6 @@ import {
9
10
  reloadDOMNodesUsingUrl,
10
11
  reloadJsImport,
11
12
  } from "./reload.js"
12
- import { urlHotMetas } from "./import_meta_hot.js"
13
13
 
14
14
  const reloadMessages = []
15
15
  const reloadMessagesSignal = { onchange: () => {} }
@@ -0,0 +1,46 @@
1
+ import { urlIsInsideOf } from "@jsenv/filesystem"
2
+
3
+ import {
4
+ parseHtmlString,
5
+ stringifyHtmlAst,
6
+ injectScriptAsEarlyAsPossible,
7
+ createHtmlNode,
8
+ } from "@jsenv/utils/html_ast/html_ast.js"
9
+ import { jsenvRootDirectoryUrl } from "@jsenv/core/src/jsenv_root_directory_url.js"
10
+
11
+ export const jsenvPluginDevSSEClient = ({ rootDirectoryUrl }) => {
12
+ const preferSourceFiles =
13
+ rootDirectoryUrl === jsenvRootDirectoryUrl ||
14
+ urlIsInsideOf(rootDirectoryUrl, jsenvRootDirectoryUrl)
15
+ const eventSourceClientFileUrl = preferSourceFiles
16
+ ? new URL("./client/event_source_client.js", import.meta.url).href
17
+ : new URL("./dist/event_source_client.js", jsenvRootDirectoryUrl).href
18
+
19
+ return {
20
+ name: "jsenv:dev_sse_client",
21
+ appliesDuring: { dev: true },
22
+ transformUrlContent: {
23
+ html: (htmlUrlInfo, context) => {
24
+ const htmlAst = parseHtmlString(htmlUrlInfo.content)
25
+ const [eventSourceClientReference] = context.referenceUtils.inject({
26
+ type: "script_src",
27
+ expectedType: "js_module",
28
+ specifier: eventSourceClientFileUrl,
29
+ })
30
+ injectScriptAsEarlyAsPossible(
31
+ htmlAst,
32
+ createHtmlNode({
33
+ "tagName": "script",
34
+ "type": "module",
35
+ "src": eventSourceClientReference.generatedSpecifier,
36
+ "injected-by": "jsenv:dev_sse_client",
37
+ }),
38
+ )
39
+ const htmlModified = stringifyHtmlAst(htmlAst)
40
+ return {
41
+ content: htmlModified,
42
+ }
43
+ },
44
+ },
45
+ }
46
+ }