@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
@@ -4,47 +4,49 @@ import {
4
4
  isFileSystemPath,
5
5
  fileSystemPathToUrl,
6
6
  moveUrl,
7
- fileSystemRootUrl,
7
+ ensureWindowsDriveLetter,
8
8
  } from "@jsenv/filesystem"
9
+ import { createDetailedMessage } from "@jsenv/logger"
9
10
 
10
11
  import { stringifyUrlSite } from "@jsenv/utils/urls/url_trace.js"
12
+ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
13
+ import { setUrlFilename } from "@jsenv/utils/urls/url_utils.js"
11
14
 
15
+ import { createPluginController } from "../plugins/plugin_controller.js"
12
16
  import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js"
13
- import { featuresCompatMap } from "./runtime_support/features_compatibility.js"
14
- import { isFeatureSupportedOnRuntimes } from "./runtime_support/runtime_support.js"
15
- import { fileUrlConverter } from "./file_url_converter.js"
16
- import { parseUrlMentions } from "./url_mentions/parse_url_mentions.js"
17
+ import { RUNTIME_COMPAT } from "./compat/runtime_compat.js"
18
+ import { defaultRuntimeCompat } from "./compat/default_runtime_compat.js"
17
19
  import {
18
- createResolveError,
19
- createLoadError,
20
- createParseError,
21
- createTransformError,
20
+ createResolveUrlError,
21
+ createFetchUrlContentError,
22
+ createTransformUrlContentError,
23
+ createFinalizeUrlContentError,
22
24
  } from "./errors.js"
23
- import { createPluginController } from "./plugin_controller.js"
25
+ import { assertFetchedContentCompliance } from "./fetched_content_compliance.js"
26
+ import { isWebWorkerEntryPointReference } from "./web_workers.js"
24
27
 
25
28
  export const createKitchen = ({
26
29
  signal,
27
30
  logger,
28
31
  rootDirectoryUrl,
29
32
  urlGraph,
33
+
30
34
  plugins,
31
35
  scenario,
32
-
33
36
  sourcemaps = {
34
37
  dev: "inline", // "programmatic" and "file" also allowed
35
38
  test: "inline",
36
39
  build: "none",
37
40
  }[scenario],
38
- // we don't need sources in sourcemap as long as the url in the
39
- // sourcemap uses file:/// (chrome will understand and read from filesystem)
40
- sourcemapsSources = false,
41
- loadInlineUrlInfos = (urlInfo) => {
42
- return {
43
- contentType: urlInfo.contentType,
44
- content: urlInfo.content,
45
- }
46
- },
47
-
41
+ sourcemapsSources = {
42
+ // during dev/test, chrome is able to find the sourcemap sources
43
+ // as long as they use file:// protocol in the sourcemap files
44
+ dev: false,
45
+ test: false,
46
+ build: true,
47
+ }[scenario],
48
+ sourcemapsRelativeSources,
49
+ runtimeCompat = defaultRuntimeCompat,
48
50
  writeOnFileSystem = true,
49
51
  }) => {
50
52
  const pluginController = createPluginController({
@@ -59,35 +61,76 @@ export const createKitchen = ({
59
61
  sourcemaps,
60
62
  urlGraph,
61
63
  scenario,
64
+ runtimeCompat,
65
+ isSupportedOnFutureClients: (feature) => {
66
+ return RUNTIME_COMPAT.isSupported(runtimeCompat, feature)
67
+ },
62
68
  }
63
69
  const createReference = ({
64
70
  data = {},
71
+ node,
65
72
  trace,
66
73
  parentUrl,
67
74
  type,
68
75
  subtype,
76
+ expectedContentType,
77
+ expectedType,
78
+ expectedSubtype,
79
+ filename,
80
+ integrity,
81
+ crossorigin,
69
82
  specifier,
83
+ baseUrl,
84
+ isOriginalPosition,
85
+ line,
86
+ column,
87
+ external = false,
70
88
  isInline = false,
89
+ injected = false,
90
+ isRessourceHint = false,
71
91
  content,
72
92
  contentType,
73
93
  }) => {
74
94
  return {
95
+ original: null,
96
+ prev: null,
97
+ next: null,
75
98
  data,
99
+ node,
76
100
  trace,
77
101
  parentUrl,
78
102
  type,
79
103
  subtype,
104
+ expectedContentType,
105
+ expectedType,
106
+ expectedSubtype,
107
+ filename,
108
+ integrity,
109
+ crossorigin,
80
110
  specifier,
111
+ baseUrl,
112
+ isOriginalPosition,
113
+ line,
114
+ column,
115
+ external,
81
116
  isInline,
117
+ injected,
118
+ isRessourceHint,
82
119
  // for inline ressources the reference contains the content
83
120
  content,
84
121
  contentType,
122
+ timing: {},
85
123
  }
86
124
  }
125
+ const mutateReference = (reference, newReference) => {
126
+ reference.next = newReference
127
+ newReference.prev = reference
128
+ newReference.original = reference.original || reference
129
+ }
87
130
  const resolveReference = (reference) => {
88
131
  try {
89
132
  const resolvedUrl = pluginController.callHooksUntil(
90
- "resolve",
133
+ "resolveUrl",
91
134
  reference,
92
135
  baseContext,
93
136
  )
@@ -95,15 +138,25 @@ export const createKitchen = ({
95
138
  throw new Error(`NO_RESOLVE`)
96
139
  }
97
140
  reference.url = resolvedUrl
141
+ if (reference.external) {
142
+ reference.generatedUrl = resolvedUrl
143
+ reference.generatedSpecifier = reference.specifier
144
+ return urlGraph.reuseOrCreateUrlInfo(reference.url)
145
+ }
98
146
  pluginController.callHooks(
99
- "normalize",
147
+ "normalizeUrl",
100
148
  reference,
101
149
  baseContext,
102
150
  (returnValue) => {
151
+ if (returnValue === reference.url) {
152
+ return
153
+ }
154
+ const previousReference = { ...reference }
103
155
  reference.url = returnValue
156
+ mutateReference(previousReference, reference)
104
157
  },
105
158
  )
106
- // force a last normalization regarding on url search params
159
+ // force a last normalization on url search params
107
160
  // some plugin use URLSearchParams to alter the url search params
108
161
  // which can result into "file:///file.css?css_module"
109
162
  // becoming "file:///file.css?css_module="
@@ -115,49 +168,59 @@ export const createKitchen = ({
115
168
  reference.url = reference.url.replace(/[=](?=&|$)/g, "")
116
169
  }
117
170
  const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
118
- Object.assign(urlInfo.data, reference.data)
171
+ applyReferenceEffectsOnUrlInfo(reference, urlInfo, baseContext)
119
172
 
120
- // create a copy because .url will be mutated
121
- const referencedCopy = {
122
- ...reference,
123
- data: urlInfo.data,
124
- }
173
+ const referenceUrlObject = new URL(reference.url)
174
+ reference.searchParams = referenceUrlObject.searchParams
175
+ reference.generatedUrl = reference.url
176
+ // This hook must touch reference.generatedUrl, NOT reference.url
177
+ // And this is because this hook inject query params used to:
178
+ // - bypass browser cache (?v)
179
+ // - convey information (?hmr)
180
+ // But do not represent an other ressource, it is considered as
181
+ // the same ressource under the hood
125
182
  pluginController.callHooks(
126
- "transformReferencedUrl",
127
- referencedCopy,
183
+ "transformUrlSearchParams",
184
+ reference,
128
185
  baseContext,
129
186
  (returnValue) => {
130
- referencedCopy.url = returnValue
187
+ Object.keys(returnValue).forEach((key) => {
188
+ referenceUrlObject.searchParams.set(key, returnValue[key])
189
+ })
190
+ reference.generatedUrl = referenceUrlObject.href.replace(
191
+ /[=](?=&|$)/g,
192
+ "",
193
+ )
131
194
  },
132
195
  )
133
- reference.generatedUrl = referencedCopy.url
134
196
  const returnValue = pluginController.callHooksUntil(
135
- "formatReferencedUrl",
136
- referencedCopy,
197
+ "formatUrl",
198
+ reference,
137
199
  baseContext,
138
200
  )
139
201
  reference.generatedSpecifier = returnValue || reference.generatedUrl
140
- reference.generatedSpecifier = specifierFormat.encode(reference)
202
+ reference.generatedSpecifier = urlSpecifierFormat.encode(reference)
141
203
  return urlInfo
142
204
  } catch (error) {
143
- throw createResolveError({
205
+ throw createResolveUrlError({
144
206
  pluginController,
145
207
  reference,
146
208
  error,
147
209
  })
148
210
  }
149
211
  }
212
+ baseContext.resolveReference = resolveReference
150
213
  const urlInfoTransformer = createUrlInfoTransformer({
151
214
  logger,
152
215
  urlGraph,
153
216
  sourcemaps,
154
217
  sourcemapsSources,
218
+ sourcemapsRelativeSources,
155
219
  injectSourcemapPlaceholder: ({ urlInfo, specifier }) => {
156
220
  const sourcemapReference = createReference({
157
221
  trace: `sourcemap comment placeholder for ${urlInfo.url}`,
158
222
  type: "sourcemap_comment",
159
- subtype:
160
- urlInfo.contentType === "application/javascript" ? "js" : "css",
223
+ subtype: urlInfo.contentType === "text/javascript" ? "js" : "css",
161
224
  parentUrl: urlInfo.url,
162
225
  specifier,
163
226
  })
@@ -185,69 +248,77 @@ export const createKitchen = ({
185
248
  },
186
249
  })
187
250
 
188
- const isSupported = ({
189
- runtimeSupport,
190
- featureName,
191
- featureCompat = featuresCompatMap[featureName],
192
- }) => {
193
- return isFeatureSupportedOnRuntimes(runtimeSupport, featureCompat)
194
- }
195
-
196
- const load = async ({ reference, urlInfo, context }) => {
251
+ const fetchUrlContent = async ({ reference, urlInfo, context }) => {
252
+ if (reference.external) {
253
+ urlInfo.external = true
254
+ return
255
+ }
197
256
  try {
198
- const loadReturnValue = urlInfo.isInline
199
- ? loadInlineUrlInfos(urlInfo)
200
- : await pluginController.callAsyncHooksUntil("load", urlInfo, context)
201
- if (!loadReturnValue) {
202
- throw new Error("NO_LOAD")
257
+ const returnValue = await pluginController.callAsyncHooksUntil(
258
+ "fetchUrlContent",
259
+ urlInfo,
260
+ context,
261
+ )
262
+ if (!returnValue) {
263
+ logger.warn(
264
+ createDetailedMessage(
265
+ `no plugin has handled the url during "fetchUrlContent" hook -> consider url as external (ignore it)`,
266
+ {
267
+ "url": urlInfo.url,
268
+ "url reference trace": reference.trace,
269
+ },
270
+ ),
271
+ )
272
+ urlInfo.external = true
273
+ return
274
+ }
275
+ if (returnValue.external) {
276
+ urlInfo.external = true
277
+ return
203
278
  }
204
-
205
279
  const {
206
- contentType = "application/octet-stream",
207
- content, // can be a buffer (used for binary files) or a string
208
- sourcemap,
209
- // during build urls info are reused and load returns originalContent
210
- // that we want to keep
211
- originalContent = content,
212
280
  data,
213
- } = loadReturnValue
214
- Object.assign(urlInfo, {
215
- contentType,
281
+ type,
282
+ subtype,
283
+ contentType = "application/octet-stream",
216
284
  originalContent,
217
285
  content,
218
286
  sourcemap,
219
- })
287
+ filename,
288
+ } = returnValue
289
+ urlInfo.type =
290
+ type ||
291
+ reference.expectedType ||
292
+ inferUrlInfoType({
293
+ url: urlInfo.url,
294
+ contentType,
295
+ })
296
+ urlInfo.subtype =
297
+ subtype ||
298
+ reference.expectedSubtype ||
299
+ inferUrlInfoSubtype({
300
+ url: urlInfo.url,
301
+ type: urlInfo.type,
302
+ subtype: urlInfo.subtype,
303
+ })
304
+ urlInfo.contentType = contentType
305
+ // during build urls info are reused and load returns originalContent
306
+ urlInfo.originalContent =
307
+ originalContent === undefined ? content : originalContent
308
+ urlInfo.content = content
309
+ urlInfo.sourcemap = sourcemap
220
310
  if (data) {
221
311
  Object.assign(urlInfo.data, data)
222
312
  }
223
- if (!urlInfo.type) {
224
- const type = inferUrlInfoType(urlInfo)
225
- if (type === "js") {
226
- const urlObject = new URL(urlInfo.url)
227
- if (urlObject.searchParams.has("worker_type_classic")) {
228
- urlInfo.type = "js_classic"
229
- urlInfo.subtype = "worker"
230
- } else if (
231
- urlObject.searchParams.has("service_worker_type_classic")
232
- ) {
233
- urlInfo.type = "js_classic"
234
- urlInfo.subtype = "service_worker"
235
- } else if (urlObject.searchParams.has("js_classic")) {
236
- urlInfo.type = "js_classic"
237
- } else {
238
- urlInfo.type = "js_module"
239
- }
240
- if (urlObject.searchParams.has("worker")) {
241
- urlInfo.subtype = "worker"
242
- } else if (urlObject.searchParams.has("service_worker")) {
243
- urlInfo.subtype = "service_worker"
244
- }
245
- } else {
246
- urlInfo.type = type
247
- }
313
+ if (filename) {
314
+ urlInfo.filename = filename
248
315
  }
316
+ assertFetchedContentCompliance({
317
+ reference,
318
+ urlInfo,
319
+ })
249
320
  } catch (error) {
250
- throw createLoadError({
321
+ throw createFetchUrlContentError({
251
322
  pluginController,
252
323
  urlInfo,
253
324
  reference,
@@ -255,9 +326,8 @@ export const createKitchen = ({
255
326
  })
256
327
  }
257
328
  urlInfo.generatedUrl = determineFileUrlForOutDirectory({
258
- rootDirectoryUrl,
259
- outDirectoryUrl: context.outDirectoryUrl,
260
- url: urlInfo.url,
329
+ urlInfo,
330
+ context,
261
331
  })
262
332
  await urlInfoTransformer.initTransformations(urlInfo, context)
263
333
  }
@@ -266,34 +336,39 @@ export const createKitchen = ({
266
336
  reference,
267
337
  urlInfo,
268
338
  outDirectoryUrl,
269
- runtimeSupport,
339
+ // during dev/test clientRuntimeCompat is a single runtime
340
+ // during build clientRuntimeCompat is runtimeCompat
341
+ clientRuntimeCompat = runtimeCompat,
270
342
  cookDuringCook = cook,
271
343
  }) => {
272
344
  const context = {
273
345
  ...baseContext,
274
346
  reference,
275
347
  outDirectoryUrl,
276
- runtimeSupport,
277
- isSupportedOnRuntime: (featureName, featureCompat) => {
278
- return isSupported({ runtimeSupport, featureName, featureCompat })
348
+ clientRuntimeCompat,
349
+ isSupportedOnCurrentClients: (feature) => {
350
+ return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
279
351
  },
280
352
  cook: (params) => {
281
353
  return cookDuringCook({
282
354
  outDirectoryUrl,
283
- runtimeSupport,
355
+ clientRuntimeCompat,
284
356
  ...params,
285
357
  })
286
358
  },
287
- load: (params) => {
288
- return load({
359
+ fetchUrlContent: (params) => {
360
+ return fetchUrlContent({
289
361
  context,
290
362
  ...params,
291
363
  })
292
364
  },
293
365
  }
294
366
 
295
- // "load" hook
296
- await load({ reference, urlInfo, context })
367
+ // "fetchUrlContent" hook
368
+ await fetchUrlContent({ reference, urlInfo, context })
369
+ if (urlInfo.external) {
370
+ return
371
+ }
297
372
 
298
373
  // parsing
299
374
  const references = []
@@ -303,182 +378,146 @@ export const createKitchen = ({
303
378
  ...props,
304
379
  })
305
380
  references.push(reference)
306
- return [reference, resolveReference(reference)]
381
+ const referencedUrlInfo = resolveReference(reference)
382
+ return [reference, referencedUrlInfo]
307
383
  }
308
384
  const referenceUtils = {
309
- inject: ({ trace, ...rest }) => {
310
- if (trace === undefined) {
311
- const { prepareStackTrace } = Error
312
- Error.prepareStackTrace = (error, stack) => {
313
- Error.prepareStackTrace = prepareStackTrace
314
- return stack
315
- }
316
- const { stack } = new Error()
317
- const callerCallsite = stack[1]
318
- const fileName = callerCallsite.getFileName()
319
- trace = stringifyUrlSite({
320
- url:
321
- fileName && isFileSystemPath(fileName)
322
- ? fileSystemPathToUrl(fileName)
323
- : fileName,
324
- line: callerCallsite.getLineNumber(),
325
- column: callerCallsite.getColumnNumber(),
385
+ readGeneratedSpecifier: async (reference) => {
386
+ // "formatReferencedUrl" can be async BUT this is an exception
387
+ // for most cases it will be sync. We want to favor the sync signature to keep things simpler
388
+ // The only case where it needs to be async is when
389
+ // the specifier is a `data:*` url
390
+ // in this case we'll wait for the promise returned by
391
+ // "formatReferencedUrl"
392
+ if (reference.generatedSpecifier.then) {
393
+ return reference.generatedSpecifier.then((value) => {
394
+ reference.generatedSpecifier = value
395
+ return value
326
396
  })
327
397
  }
398
+ return reference.generatedSpecifier
399
+ },
400
+ found: ({ line, column, ...rest }) => {
401
+ const trace = stringifyUrlSite(
402
+ adjustUrlSite(urlInfo, {
403
+ urlGraph,
404
+ url: urlInfo.url,
405
+ line,
406
+ column,
407
+ }),
408
+ )
409
+ // console.log(trace)
328
410
  return addReference({
329
411
  trace,
412
+ line,
413
+ column,
330
414
  ...rest,
331
415
  })
332
416
  },
333
- foundInline: ({
334
- type,
335
- isOriginal,
336
- line,
337
- column,
338
- specifier,
339
- contentType,
340
- content,
341
- }) => {
342
- const parentUrl = isOriginal ? urlInfo.url : urlInfo.generatedUrl
343
- const parentContent = isOriginal
417
+ foundInline: ({ isOriginalPosition, line, column, ...rest }) => {
418
+ const parentUrl = isOriginalPosition
419
+ ? urlInfo.url
420
+ : urlInfo.generatedUrl
421
+ const parentContent = isOriginalPosition
344
422
  ? urlInfo.originalContent
345
423
  : urlInfo.content
346
- const [inlineReference, inlineUrlInfo] = addReference({
424
+ return addReference({
347
425
  trace: stringifyUrlSite({
348
426
  url: parentUrl,
349
427
  content: parentContent,
350
428
  line,
351
429
  column,
352
430
  }),
353
- type,
354
- specifier,
355
- isInline: true,
356
- contentType,
357
- content,
358
- })
359
- inlineUrlInfo.isInline = true
360
- inlineUrlInfo.inlineUrlSite = {
361
- url: urlInfo.url,
362
- content: parentContent,
431
+ isOriginalPosition,
363
432
  line,
364
433
  column,
365
- }
366
- inlineUrlInfo.contentType = contentType
367
- inlineUrlInfo.originalContent = inlineUrlInfo.content = content
368
- return [inlineReference, inlineUrlInfo]
434
+ isInline: true,
435
+ ...rest,
436
+ })
369
437
  },
370
- updateSpecifier: (generatedSpecifier, newSpecifier, data) => {
371
- const index = references.findIndex(
372
- (ref) => ref.generatedSpecifier === generatedSpecifier,
373
- )
438
+ update: (currentReference, newReferenceParams) => {
439
+ const index = references.indexOf(currentReference)
374
440
  if (index === -1) {
375
- throw new Error(
376
- `Cannot find a reference for the following generatedSpecifier "${generatedSpecifier}"`,
377
- )
441
+ throw new Error(`reference do not exists`)
378
442
  }
379
- const referenceFound = references[index]
380
- const newReference = createReference({
381
- ...referenceFound,
382
- specifier: newSpecifier,
383
- data: {
384
- ...referenceFound.data,
385
- ...data,
386
- },
443
+ const previousReference = currentReference
444
+ const nextReference = createReference({
445
+ ...previousReference,
446
+ ...newReferenceParams,
387
447
  })
388
- references[index] = newReference
389
- newReference.data.originalReference = referenceFound
390
- const newUrlInfo = resolveReference(newReference)
391
- return [newReference, newUrlInfo]
448
+ references[index] = nextReference
449
+ mutateReference(previousReference, nextReference)
450
+ const newUrlInfo = resolveReference(nextReference)
451
+ const currentUrlInfo = context.urlGraph.getUrlInfo(currentReference.url)
452
+ if (
453
+ currentUrlInfo &&
454
+ currentUrlInfo !== newUrlInfo &&
455
+ currentUrlInfo.dependents.size === 0
456
+ ) {
457
+ context.urlGraph.deleteUrlInfo(currentReference.url)
458
+ }
459
+ return [nextReference, newUrlInfo]
392
460
  },
393
461
  becomesInline: (
394
462
  reference,
395
- { isOriginal, line, column, specifier, contentType, content },
463
+ { isOriginalPosition, line, column, specifier, contentType, content },
396
464
  ) => {
397
- const parentUrl = isOriginal ? urlInfo.url : urlInfo.generatedUrl
398
- const parentContent = isOriginal
465
+ const parentUrl = isOriginalPosition
466
+ ? urlInfo.url
467
+ : urlInfo.generatedUrl
468
+ const parentContent = isOriginalPosition
399
469
  ? urlInfo.originalContent
400
470
  : urlInfo.content
401
- reference.trace = stringifyUrlSite({
402
- url: parentUrl,
403
- content: parentContent,
404
- line,
405
- column,
471
+ return referenceUtils.update(reference, {
472
+ trace: stringifyUrlSite({
473
+ url: parentUrl,
474
+ content: parentContent,
475
+ line,
476
+ column,
477
+ }),
478
+ isOriginalPosition,
479
+ isInline: true,
480
+ specifier,
481
+ contentType,
482
+ content,
406
483
  })
407
- reference.isInline = true
408
- reference.specifier = specifier
409
- reference.contentType = contentType
410
- reference.content = content
411
- const inlineUrlInfo = resolveReference(reference)
412
- inlineUrlInfo.isInline = true
413
- inlineUrlInfo.inlineUrlSite = {
414
- url: urlInfo.url,
415
- content: parentContent,
416
- line,
417
- column,
418
- }
419
- inlineUrlInfo.contentType = contentType
420
- inlineUrlInfo.content = content
421
- return reference
422
484
  },
423
- }
424
-
425
- let parseResult
426
- try {
427
- parseResult = await parseUrlMentions({
428
- type: urlInfo.type,
429
- url: urlInfo.data.sourceUrl || urlInfo.url,
430
- generatedUrl: urlInfo.generatedUrl,
431
- content: urlInfo.content,
432
- })
433
- } catch (error) {
434
- throw createParseError({
435
- reference,
436
- urlInfo,
437
- error,
438
- })
439
- }
440
- if (parseResult) {
441
- Object.assign(urlInfo.data, parseResult.data)
442
- const { urlMentions, replaceUrls } = parseResult
443
- for (const urlMention of urlMentions) {
444
- const [reference] = addReference({
445
- trace: stringifyUrlSite(
446
- adjustUrlSite(urlInfo, {
447
- urlGraph,
448
- url: urlInfo.url,
449
- line: urlMention.line,
450
- column: urlMention.column,
451
- }),
452
- ),
453
- type: urlMention.type,
454
- subtype: urlMention.subtype,
455
- specifier: urlMention.specifier,
456
- })
457
- urlMention.reference = reference
458
- }
459
- if (references.length) {
460
- // "formatReferencedUrl" can be async BUT this is an exception
461
- // for most cases it will be sync. We want to favor the sync signature to keep things simpler
462
- // The only case where it needs to be async is when
463
- // the specifier is a `data:*` url
464
- // in this case we'll wait for the promise returned by
465
- // "formatReferencedUrl"
466
- await Promise.all(
467
- references.map(async (reference) => {
468
- if (reference.generatedSpecifier.then) {
469
- const value = await reference.generatedSpecifier
470
- reference.generatedSpecifier = value
471
- }
472
- }),
473
- )
474
- const replaceReturnValue = await replaceUrls((urlMention) => {
475
- return urlMention.reference.generatedSpecifier
485
+ inject: ({ trace, ...rest }) => {
486
+ if (trace === undefined) {
487
+ const { prepareStackTrace } = Error
488
+ Error.prepareStackTrace = (error, stack) => {
489
+ Error.prepareStackTrace = prepareStackTrace
490
+ return stack
491
+ }
492
+ const { stack } = new Error()
493
+ const callerCallsite = stack[1]
494
+ const fileName = callerCallsite.getFileName()
495
+ trace = stringifyUrlSite({
496
+ url:
497
+ fileName && isFileSystemPath(fileName)
498
+ ? fileSystemPathToUrl(fileName)
499
+ : fileName,
500
+ line: callerCallsite.getLineNumber(),
501
+ column: callerCallsite.getColumnNumber(),
502
+ })
503
+ }
504
+ return addReference({
505
+ trace,
506
+ injected: true,
507
+ ...rest,
476
508
  })
477
- await urlInfoTransformer.applyIntermediateTransformations(
478
- urlInfo,
479
- replaceReturnValue,
509
+ },
510
+ findByGeneratedSpecifier: (generatedSpecifier) => {
511
+ const reference = references.find(
512
+ (ref) => ref.generatedSpecifier === generatedSpecifier,
480
513
  )
481
- }
514
+ if (!reference) {
515
+ throw new Error(
516
+ `No reference found using the following generatedSpecifier: "${generatedSpecifier}"`,
517
+ )
518
+ }
519
+ return reference
520
+ },
482
521
  }
483
522
 
484
523
  // "transform" hook
@@ -486,7 +525,7 @@ export const createKitchen = ({
486
525
  context.referenceUtils = referenceUtils
487
526
  try {
488
527
  await pluginController.callAsyncHooks(
489
- "transform",
528
+ "transformUrlContent",
490
529
  urlInfo,
491
530
  context,
492
531
  async (transformReturnValue) => {
@@ -497,7 +536,7 @@ export const createKitchen = ({
497
536
  },
498
537
  )
499
538
  } catch (error) {
500
- throw createTransformError({
539
+ throw createTransformUrlContentError({
501
540
  pluginController,
502
541
  reference,
503
542
  urlInfo,
@@ -509,15 +548,24 @@ export const createKitchen = ({
509
548
  urlGraph.updateReferences(urlInfo, references)
510
549
 
511
550
  // "finalize" hook
512
- const finalizeReturnValue = await pluginController.callHooksUntil(
513
- "finalize",
514
- urlInfo,
515
- context,
516
- )
517
- await urlInfoTransformer.applyFinalTransformations(
518
- urlInfo,
519
- finalizeReturnValue,
520
- )
551
+ try {
552
+ const finalizeReturnValue = await pluginController.callAsyncHooksUntil(
553
+ "finalizeUrlContent",
554
+ urlInfo,
555
+ context,
556
+ )
557
+ await urlInfoTransformer.applyFinalTransformations(
558
+ urlInfo,
559
+ finalizeReturnValue,
560
+ )
561
+ } catch (error) {
562
+ throw createFinalizeUrlContentError({
563
+ pluginController,
564
+ reference,
565
+ urlInfo,
566
+ error,
567
+ })
568
+ }
521
569
 
522
570
  // "cooked" hook
523
571
  pluginController.callHooks(
@@ -580,15 +628,63 @@ export const createKitchen = ({
580
628
 
581
629
  baseContext.cook = cook
582
630
 
631
+ const prepareEntryPoint = (params) => {
632
+ const entryReference = createReference(params)
633
+ const entryUrlInfo = resolveReference(entryReference)
634
+ // I should likely delete urlInfo.sourcemap
635
+ // otherwise it is reused when page is reloaded
636
+ return [entryReference, entryUrlInfo]
637
+ }
638
+
639
+ const injectReference = (params) => {
640
+ const ref = createReference(params)
641
+ const urlInfo = resolveReference(ref)
642
+ return [ref, urlInfo]
643
+ }
644
+
583
645
  return {
584
646
  pluginController,
585
647
  urlInfoTransformer,
586
648
  rootDirectoryUrl,
587
649
  jsenvDirectoryUrl,
588
- isSupported,
589
- createReference,
590
- resolveReference,
650
+ baseContext,
591
651
  cook,
652
+ prepareEntryPoint,
653
+ injectReference,
654
+ }
655
+ }
656
+
657
+ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
658
+ Object.assign(urlInfo.data, reference.data)
659
+ Object.assign(urlInfo.timing, reference.timing)
660
+ if (reference.injected) {
661
+ urlInfo.data.injected = true
662
+ }
663
+ if (reference.filename) {
664
+ urlInfo.filename = reference.filename
665
+ }
666
+ if (reference.isInline) {
667
+ urlInfo.isInline = true
668
+ const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
669
+ urlInfo.inlineUrlSite = {
670
+ url: parentUrlInfo.url,
671
+ content: reference.isOriginalPosition
672
+ ? parentUrlInfo.originalContent
673
+ : parentUrlInfo.content,
674
+ line: reference.line,
675
+ column: reference.column,
676
+ }
677
+ urlInfo.contentType = reference.contentType
678
+ urlInfo.originalContent =
679
+ context === "build"
680
+ ? urlInfo.originalContent === undefined
681
+ ? reference.content
682
+ : urlInfo.originalContent
683
+ : reference.content
684
+ urlInfo.content = reference.content
685
+ }
686
+ if (isWebWorkerEntryPointReference(reference)) {
687
+ urlInfo.data.isWebWorkerEntryPoint = true
592
688
  }
593
689
  }
594
690
 
@@ -626,54 +722,86 @@ const adjustUrlSite = (urlInfo, { urlGraph, url, line, column }) => {
626
722
  )
627
723
  }
628
724
 
629
- const inferUrlInfoType = ({ contentType }) => {
725
+ const inferUrlInfoType = ({ url, contentType }) => {
630
726
  if (contentType === "text/html") {
631
727
  return "html"
632
728
  }
633
729
  if (contentType === "text/css") {
634
730
  return "css"
635
731
  }
636
- if (contentType === "application/javascript") {
637
- return "js"
638
- }
639
- if (contentType === "application/json") {
640
- return "json"
732
+ if (contentType === "text/javascript") {
733
+ const urlObject = new URL(url)
734
+ if (urlObject.searchParams.has("js_classic")) {
735
+ return "js_classic"
736
+ }
737
+ return "js_module"
641
738
  }
642
739
  if (contentType === "application/importmap+json") {
643
740
  return "importmap"
644
741
  }
742
+ if (contentType === "application/manifest+json") {
743
+ return "webmanifest"
744
+ }
745
+ if (contentType === "image/svg+xml") {
746
+ return "svg"
747
+ }
748
+ if (CONTENT_TYPE.isJson(contentType)) {
749
+ return "json"
750
+ }
751
+ if (CONTENT_TYPE.isTextual(contentType)) {
752
+ return "text"
753
+ }
645
754
  return "other"
646
755
  }
647
756
 
648
- const determineFileUrlForOutDirectory = ({
649
- rootDirectoryUrl,
650
- outDirectoryUrl,
651
- url,
652
- }) => {
653
- if (!outDirectoryUrl) {
654
- return url
757
+ const inferUrlInfoSubtype = ({ type, subtype, url }) => {
758
+ if (type === "js_classic" || type === "js_module") {
759
+ const urlObject = new URL(url)
760
+ if (urlObject.searchParams.has("worker")) {
761
+ return "worker"
762
+ }
763
+ if (urlObject.searchParams.has("service_worker")) {
764
+ return "service_worker"
765
+ }
766
+ if (urlObject.searchParams.has("shared_worker")) {
767
+ return "shared_worker"
768
+ }
769
+ // if we are currently inside a worker, all deps are consider inside worker too
770
+ return subtype
771
+ }
772
+ return ""
773
+ }
774
+
775
+ const determineFileUrlForOutDirectory = ({ urlInfo, context }) => {
776
+ if (!context.outDirectoryUrl) {
777
+ return urlInfo.url
778
+ }
779
+ if (!urlInfo.url.startsWith("file:")) {
780
+ return urlInfo.url
655
781
  }
656
- if (!url.startsWith("file:")) {
657
- return url
782
+ let url = urlInfo.url
783
+ if (!urlIsInsideOf(urlInfo.url, context.rootDirectoryUrl)) {
784
+ const fsRootUrl = ensureWindowsDriveLetter("file:///", urlInfo.url)
785
+ url = `${context.rootDirectoryUrl}@fs/${url.slice(fsRootUrl.length)}`
658
786
  }
659
- if (!urlIsInsideOf(url, rootDirectoryUrl)) {
660
- url = `${rootDirectoryUrl}@fs/${url.slice(fileSystemRootUrl.length)}`
787
+ if (urlInfo.filename) {
788
+ url = setUrlFilename(url, urlInfo.filename)
661
789
  }
662
790
  return moveUrl({
663
- url: fileUrlConverter.asUrlWithoutSpecialParams(url),
664
- from: rootDirectoryUrl,
665
- to: outDirectoryUrl,
791
+ url,
792
+ from: context.rootDirectoryUrl,
793
+ to: context.outDirectoryUrl,
666
794
  preferAbsolute: true,
667
795
  })
668
796
  }
669
797
 
670
- const specifierFormat = {
798
+ const urlSpecifierFormat = {
671
799
  encode: (reference) => {
672
800
  const { generatedSpecifier } = reference
673
801
  if (generatedSpecifier.then) {
674
802
  return generatedSpecifier.then((value) => {
675
803
  reference.generatedSpecifier = value
676
- return specifierFormat.encode(reference)
804
+ return urlSpecifierFormat.encode(reference)
677
805
  })
678
806
  }
679
807
  // allow plugin to return a function to bypas default formatting
@@ -698,10 +826,11 @@ const specifierFormat = {
698
826
  },
699
827
  }
700
828
  const formatters = {
701
- js_import_export: { encode: JSON.stringify, decode: JSON.parse },
702
- js_import_meta_url_pattern: { encode: JSON.stringify, decode: JSON.parse },
829
+ "js_import_export": { encode: JSON.stringify, decode: JSON.parse },
830
+ "js_url_specifier": { encode: JSON.stringify, decode: JSON.parse },
831
+ "css_@import": { encode: JSON.stringify, code: JSON.stringify },
703
832
  // https://github.com/webpack-contrib/css-loader/pull/627/files
704
- css_url: {
833
+ "css_url": {
705
834
  encode: (url) => {
706
835
  // If url is already wrapped in quotes, remove them
707
836
  url = formatters.css_url.decode(url)