@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
@@ -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 { normalizeUrl, 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
+ sourcemapsSourcesContent = {
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,105 +61,168 @@ 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
+ specifierStart,
84
+ specifierEnd,
85
+ specifierLine,
86
+ specifierColumn,
87
+ baseUrl,
88
+ isOriginalPosition,
89
+ external = false,
70
90
  isInline = false,
91
+ injected = false,
92
+ isRessourceHint = false,
71
93
  content,
72
94
  contentType,
95
+ assert,
96
+ assertNode,
97
+ typePropertyNode,
73
98
  }) => {
99
+ if (typeof specifier !== "string") {
100
+ throw new TypeError(`"specifier" must be a string, got ${specifier}`)
101
+ }
74
102
  return {
103
+ original: null,
104
+ prev: null,
105
+ next: null,
75
106
  data,
107
+ node,
76
108
  trace,
77
109
  parentUrl,
78
110
  type,
79
111
  subtype,
112
+ expectedContentType,
113
+ expectedType,
114
+ expectedSubtype,
115
+ filename,
116
+ integrity,
117
+ crossorigin,
80
118
  specifier,
119
+ specifierStart,
120
+ specifierEnd,
121
+ specifierLine,
122
+ specifierColumn,
123
+ baseUrl,
124
+ isOriginalPosition,
125
+ external,
81
126
  isInline,
127
+ injected,
128
+ isRessourceHint,
82
129
  // for inline ressources the reference contains the content
83
130
  content,
84
131
  contentType,
132
+ timing: {},
133
+ assert,
134
+ assertNode,
135
+ typePropertyNode,
85
136
  }
86
137
  }
138
+ const mutateReference = (reference, newReference) => {
139
+ reference.next = newReference
140
+ newReference.prev = reference
141
+ newReference.original = reference.original || reference
142
+ }
87
143
  const resolveReference = (reference) => {
88
144
  try {
89
- const resolvedUrl = pluginController.callHooksUntil(
90
- "resolve",
145
+ let resolvedUrl = pluginController.callHooksUntil(
146
+ "resolveUrl",
91
147
  reference,
92
148
  baseContext,
93
149
  )
94
150
  if (!resolvedUrl) {
95
151
  throw new Error(`NO_RESOLVE`)
96
152
  }
153
+ resolvedUrl = normalizeUrl(resolvedUrl)
97
154
  reference.url = resolvedUrl
155
+ if (reference.external) {
156
+ reference.generatedUrl = resolvedUrl
157
+ reference.generatedSpecifier = reference.specifier
158
+ return urlGraph.reuseOrCreateUrlInfo(reference.url)
159
+ }
98
160
  pluginController.callHooks(
99
- "normalize",
161
+ "redirectUrl",
100
162
  reference,
101
163
  baseContext,
102
164
  (returnValue) => {
103
- reference.url = returnValue
165
+ const normalizedReturnValue = normalizeUrl(returnValue)
166
+ if (normalizedReturnValue === reference.url) {
167
+ return
168
+ }
169
+ const previousReference = { ...reference }
170
+ reference.url = normalizedReturnValue
171
+ mutateReference(previousReference, reference)
104
172
  },
105
173
  )
106
- // force a last normalization regarding on url search params
107
- // some plugin use URLSearchParams to alter the url search params
108
- // which can result into "file:///file.css?css_module"
109
- // becoming "file:///file.css?css_module="
110
- // we want to get rid of the "=" and consider it's the same url
111
- if (
112
- // disable on data urls (would mess up base64 encoding)
113
- !reference.url.startsWith("data:")
114
- ) {
115
- reference.url = reference.url.replace(/[=](?=&|$)/g, "")
116
- }
174
+
117
175
  const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
118
- Object.assign(urlInfo.data, reference.data)
176
+ applyReferenceEffectsOnUrlInfo(reference, urlInfo, baseContext)
119
177
 
120
- // create a copy because .url will be mutated
121
- const referencedCopy = {
122
- ...reference,
123
- data: urlInfo.data,
124
- }
178
+ const referenceUrlObject = new URL(reference.url)
179
+ reference.searchParams = referenceUrlObject.searchParams
180
+ reference.generatedUrl = reference.url
181
+ // This hook must touch reference.generatedUrl, NOT reference.url
182
+ // And this is because this hook inject query params used to:
183
+ // - bypass browser cache (?v)
184
+ // - convey information (?hmr)
185
+ // But do not represent an other ressource, it is considered as
186
+ // the same ressource under the hood
125
187
  pluginController.callHooks(
126
- "transformReferencedUrl",
127
- referencedCopy,
188
+ "transformUrlSearchParams",
189
+ reference,
128
190
  baseContext,
129
191
  (returnValue) => {
130
- referencedCopy.url = returnValue
192
+ Object.keys(returnValue).forEach((key) => {
193
+ referenceUrlObject.searchParams.set(key, returnValue[key])
194
+ })
195
+ reference.generatedUrl = normalizeUrl(referenceUrlObject.href)
131
196
  },
132
197
  )
133
- reference.generatedUrl = referencedCopy.url
134
198
  const returnValue = pluginController.callHooksUntil(
135
- "formatReferencedUrl",
136
- referencedCopy,
199
+ "formatUrl",
200
+ reference,
137
201
  baseContext,
138
202
  )
139
203
  reference.generatedSpecifier = returnValue || reference.generatedUrl
140
- reference.generatedSpecifier = specifierFormat.encode(reference)
204
+ reference.generatedSpecifier = urlSpecifierFormat.encode(reference)
141
205
  return urlInfo
142
206
  } catch (error) {
143
- throw createResolveError({
207
+ throw createResolveUrlError({
144
208
  pluginController,
145
209
  reference,
146
210
  error,
147
211
  })
148
212
  }
149
213
  }
214
+ baseContext.resolveReference = resolveReference
150
215
  const urlInfoTransformer = createUrlInfoTransformer({
151
216
  logger,
152
217
  urlGraph,
153
218
  sourcemaps,
154
- sourcemapsSources,
219
+ sourcemapsSourcesContent,
220
+ sourcemapsRelativeSources,
155
221
  injectSourcemapPlaceholder: ({ urlInfo, specifier }) => {
156
222
  const sourcemapReference = createReference({
157
223
  trace: `sourcemap comment placeholder for ${urlInfo.url}`,
158
224
  type: "sourcemap_comment",
159
- subtype:
160
- urlInfo.contentType === "application/javascript" ? "js" : "css",
225
+ subtype: urlInfo.contentType === "text/javascript" ? "js" : "css",
161
226
  parentUrl: urlInfo.url,
162
227
  specifier,
163
228
  })
@@ -165,19 +230,27 @@ export const createKitchen = ({
165
230
  sourcemapUrlInfo.type = "sourcemap"
166
231
  return [sourcemapReference, sourcemapUrlInfo]
167
232
  },
168
- foundSourcemap: ({ urlInfo, line, column, type, specifier }) => {
233
+ foundSourcemap: ({
234
+ urlInfo,
235
+ type,
236
+ specifier,
237
+ specifierLine,
238
+ specifierColumn,
239
+ }) => {
169
240
  const sourcemapReference = createReference({
170
241
  trace: stringifyUrlSite(
171
242
  adjustUrlSite(urlInfo, {
172
243
  urlGraph,
173
244
  url: urlInfo.url,
174
- line,
175
- column,
245
+ line: specifierLine,
246
+ column: specifierColumn,
176
247
  }),
177
248
  ),
178
249
  type,
179
250
  parentUrl: urlInfo.url,
180
251
  specifier,
252
+ specifierLine,
253
+ specifierColumn,
181
254
  })
182
255
  const sourcemapUrlInfo = resolveReference(sourcemapReference)
183
256
  sourcemapUrlInfo.type = "sourcemap"
@@ -185,69 +258,78 @@ export const createKitchen = ({
185
258
  },
186
259
  })
187
260
 
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 }) => {
261
+ const fetchUrlContent = async ({ reference, urlInfo, context }) => {
262
+ if (reference.external) {
263
+ urlInfo.external = true
264
+ return
265
+ }
197
266
  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")
267
+ const fetchUrlContentReturnValue =
268
+ await pluginController.callAsyncHooksUntil(
269
+ "fetchUrlContent",
270
+ urlInfo,
271
+ context,
272
+ )
273
+ if (!fetchUrlContentReturnValue) {
274
+ logger.warn(
275
+ createDetailedMessage(
276
+ `no plugin has handled the url during "fetchUrlContent" hook -> consider url as external (ignore it)`,
277
+ {
278
+ "url": urlInfo.url,
279
+ "url reference trace": reference.trace,
280
+ },
281
+ ),
282
+ )
283
+ urlInfo.external = true
284
+ return
285
+ }
286
+ if (fetchUrlContentReturnValue.external) {
287
+ urlInfo.external = true
288
+ return
203
289
  }
204
-
205
290
  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
291
  data,
213
- } = loadReturnValue
214
- Object.assign(urlInfo, {
215
- contentType,
292
+ type,
293
+ subtype,
294
+ contentType = "application/octet-stream",
216
295
  originalContent,
217
296
  content,
218
297
  sourcemap,
219
- })
298
+ filename,
299
+ } = fetchUrlContentReturnValue
300
+ urlInfo.type =
301
+ type ||
302
+ reference.expectedType ||
303
+ inferUrlInfoType({
304
+ url: urlInfo.url,
305
+ contentType,
306
+ })
307
+ urlInfo.subtype =
308
+ subtype ||
309
+ reference.expectedSubtype ||
310
+ inferUrlInfoSubtype({
311
+ url: urlInfo.url,
312
+ type: urlInfo.type,
313
+ subtype: urlInfo.subtype,
314
+ })
315
+ urlInfo.contentType = contentType
316
+ // during build urls info are reused and load returns originalContent
317
+ urlInfo.originalContent =
318
+ originalContent === undefined ? content : originalContent
319
+ urlInfo.content = content
320
+ urlInfo.sourcemap = sourcemap
220
321
  if (data) {
221
322
  Object.assign(urlInfo.data, data)
222
323
  }
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
- }
324
+ if (filename) {
325
+ urlInfo.filename = filename
248
326
  }
327
+ assertFetchedContentCompliance({
328
+ reference,
329
+ urlInfo,
330
+ })
249
331
  } catch (error) {
250
- throw createLoadError({
332
+ throw createFetchUrlContentError({
251
333
  pluginController,
252
334
  urlInfo,
253
335
  reference,
@@ -255,9 +337,8 @@ export const createKitchen = ({
255
337
  })
256
338
  }
257
339
  urlInfo.generatedUrl = determineFileUrlForOutDirectory({
258
- rootDirectoryUrl,
259
- outDirectoryUrl: context.outDirectoryUrl,
260
- url: urlInfo.url,
340
+ urlInfo,
341
+ context,
261
342
  })
262
343
  await urlInfoTransformer.initTransformations(urlInfo, context)
263
344
  }
@@ -266,34 +347,39 @@ export const createKitchen = ({
266
347
  reference,
267
348
  urlInfo,
268
349
  outDirectoryUrl,
269
- runtimeSupport,
350
+ // during dev/test clientRuntimeCompat is a single runtime
351
+ // during build clientRuntimeCompat is runtimeCompat
352
+ clientRuntimeCompat = runtimeCompat,
270
353
  cookDuringCook = cook,
271
354
  }) => {
355
+ baseContext.isSupportedOnCurrentClients = (feature) => {
356
+ return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
357
+ }
272
358
  const context = {
273
359
  ...baseContext,
274
360
  reference,
275
361
  outDirectoryUrl,
276
- runtimeSupport,
277
- isSupportedOnRuntime: (featureName, featureCompat) => {
278
- return isSupported({ runtimeSupport, featureName, featureCompat })
279
- },
362
+ clientRuntimeCompat,
280
363
  cook: (params) => {
281
364
  return cookDuringCook({
282
365
  outDirectoryUrl,
283
- runtimeSupport,
366
+ clientRuntimeCompat,
284
367
  ...params,
285
368
  })
286
369
  },
287
- load: (params) => {
288
- return load({
370
+ fetchUrlContent: (params) => {
371
+ return fetchUrlContent({
289
372
  context,
290
373
  ...params,
291
374
  })
292
375
  },
293
376
  }
294
377
 
295
- // "load" hook
296
- await load({ reference, urlInfo, context })
378
+ // "fetchUrlContent" hook
379
+ await fetchUrlContent({ reference, urlInfo, context })
380
+ if (urlInfo.external) {
381
+ return
382
+ }
297
383
 
298
384
  // parsing
299
385
  const references = []
@@ -303,182 +389,155 @@ export const createKitchen = ({
303
389
  ...props,
304
390
  })
305
391
  references.push(reference)
306
- return [reference, resolveReference(reference)]
392
+ const referencedUrlInfo = resolveReference(reference)
393
+ return [reference, referencedUrlInfo]
307
394
  }
308
395
  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(),
396
+ readGeneratedSpecifier: async (reference) => {
397
+ // "formatReferencedUrl" can be async BUT this is an exception
398
+ // for most cases it will be sync. We want to favor the sync signature to keep things simpler
399
+ // The only case where it needs to be async is when
400
+ // the specifier is a `data:*` url
401
+ // in this case we'll wait for the promise returned by
402
+ // "formatReferencedUrl"
403
+ if (reference.generatedSpecifier.then) {
404
+ return reference.generatedSpecifier.then((value) => {
405
+ reference.generatedSpecifier = value
406
+ return value
326
407
  })
327
408
  }
409
+ return reference.generatedSpecifier
410
+ },
411
+ found: ({ specifierLine, specifierColumn, ...rest }) => {
412
+ const trace = stringifyUrlSite(
413
+ adjustUrlSite(urlInfo, {
414
+ urlGraph,
415
+ url: urlInfo.url,
416
+ line: specifierLine,
417
+ column: specifierColumn,
418
+ }),
419
+ )
420
+ // console.log(trace)
328
421
  return addReference({
329
422
  trace,
423
+ specifierLine,
424
+ specifierColumn,
330
425
  ...rest,
331
426
  })
332
427
  },
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
428
+ foundInline: ({ isOriginalPosition, line, column, ...rest }) => {
429
+ const parentUrl = isOriginalPosition
430
+ ? urlInfo.url
431
+ : urlInfo.generatedUrl
432
+ const parentContent = isOriginalPosition
344
433
  ? urlInfo.originalContent
345
434
  : urlInfo.content
346
- const [inlineReference, inlineUrlInfo] = addReference({
435
+ return addReference({
347
436
  trace: stringifyUrlSite({
348
437
  url: parentUrl,
349
438
  content: parentContent,
350
439
  line,
351
440
  column,
352
441
  }),
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,
442
+ isOriginalPosition,
363
443
  line,
364
444
  column,
365
- }
366
- inlineUrlInfo.contentType = contentType
367
- inlineUrlInfo.originalContent = inlineUrlInfo.content = content
368
- return [inlineReference, inlineUrlInfo]
445
+ isInline: true,
446
+ ...rest,
447
+ })
369
448
  },
370
- updateSpecifier: (generatedSpecifier, newSpecifier, data) => {
371
- const index = references.findIndex(
372
- (ref) => ref.generatedSpecifier === generatedSpecifier,
373
- )
449
+ update: (currentReference, newReferenceParams) => {
450
+ const index = references.indexOf(currentReference)
374
451
  if (index === -1) {
375
- throw new Error(
376
- `Cannot find a reference for the following generatedSpecifier "${generatedSpecifier}"`,
377
- )
452
+ throw new Error(`reference do not exists`)
378
453
  }
379
- const referenceFound = references[index]
380
- const newReference = createReference({
381
- ...referenceFound,
382
- specifier: newSpecifier,
383
- data: {
384
- ...referenceFound.data,
385
- ...data,
386
- },
454
+ const previousReference = currentReference
455
+ const nextReference = createReference({
456
+ ...previousReference,
457
+ ...newReferenceParams,
387
458
  })
388
- references[index] = newReference
389
- newReference.data.originalReference = referenceFound
390
- const newUrlInfo = resolveReference(newReference)
391
- return [newReference, newUrlInfo]
459
+ references[index] = nextReference
460
+ mutateReference(previousReference, nextReference)
461
+ const newUrlInfo = resolveReference(nextReference)
462
+ const currentUrlInfo = context.urlGraph.getUrlInfo(currentReference.url)
463
+ if (
464
+ currentUrlInfo &&
465
+ currentUrlInfo !== newUrlInfo &&
466
+ currentUrlInfo.dependents.size === 0
467
+ ) {
468
+ context.urlGraph.deleteUrlInfo(currentReference.url)
469
+ }
470
+ return [nextReference, newUrlInfo]
392
471
  },
393
472
  becomesInline: (
394
473
  reference,
395
- { isOriginal, line, column, specifier, contentType, content },
474
+ {
475
+ isOriginalPosition,
476
+ specifier,
477
+ specifierLine,
478
+ specifierColumn,
479
+ contentType,
480
+ content,
481
+ },
396
482
  ) => {
397
- const parentUrl = isOriginal ? urlInfo.url : urlInfo.generatedUrl
398
- const parentContent = isOriginal
483
+ const parentUrl = isOriginalPosition
484
+ ? urlInfo.url
485
+ : urlInfo.generatedUrl
486
+ const parentContent = isOriginalPosition
399
487
  ? urlInfo.originalContent
400
488
  : urlInfo.content
401
- reference.trace = stringifyUrlSite({
402
- url: parentUrl,
403
- content: parentContent,
404
- line,
405
- column,
489
+ return referenceUtils.update(reference, {
490
+ trace: stringifyUrlSite({
491
+ url: parentUrl,
492
+ content: parentContent,
493
+ line: specifierLine,
494
+ column: specifierColumn,
495
+ }),
496
+ isOriginalPosition,
497
+ isInline: true,
498
+ specifier,
499
+ specifierLine,
500
+ specifierColumn,
501
+ contentType,
502
+ content,
406
503
  })
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
504
  },
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
505
+ inject: ({ trace, ...rest }) => {
506
+ if (trace === undefined) {
507
+ const { prepareStackTrace } = Error
508
+ Error.prepareStackTrace = (error, stack) => {
509
+ Error.prepareStackTrace = prepareStackTrace
510
+ return stack
511
+ }
512
+ const { stack } = new Error()
513
+ const callerCallsite = stack[1]
514
+ const fileName = callerCallsite.getFileName()
515
+ trace = stringifyUrlSite({
516
+ url:
517
+ fileName && isFileSystemPath(fileName)
518
+ ? fileSystemPathToUrl(fileName)
519
+ : fileName,
520
+ line: callerCallsite.getLineNumber(),
521
+ column: callerCallsite.getColumnNumber(),
522
+ })
523
+ }
524
+ return addReference({
525
+ trace,
526
+ injected: true,
527
+ ...rest,
476
528
  })
477
- await urlInfoTransformer.applyIntermediateTransformations(
478
- urlInfo,
479
- replaceReturnValue,
529
+ },
530
+ findByGeneratedSpecifier: (generatedSpecifier) => {
531
+ const reference = references.find(
532
+ (ref) => ref.generatedSpecifier === generatedSpecifier,
480
533
  )
481
- }
534
+ if (!reference) {
535
+ throw new Error(
536
+ `No reference found using the following generatedSpecifier: "${generatedSpecifier}"`,
537
+ )
538
+ }
539
+ return reference
540
+ },
482
541
  }
483
542
 
484
543
  // "transform" hook
@@ -486,7 +545,7 @@ export const createKitchen = ({
486
545
  context.referenceUtils = referenceUtils
487
546
  try {
488
547
  await pluginController.callAsyncHooks(
489
- "transform",
548
+ "transformUrlContent",
490
549
  urlInfo,
491
550
  context,
492
551
  async (transformReturnValue) => {
@@ -497,7 +556,7 @@ export const createKitchen = ({
497
556
  },
498
557
  )
499
558
  } catch (error) {
500
- throw createTransformError({
559
+ throw createTransformUrlContentError({
501
560
  pluginController,
502
561
  reference,
503
562
  urlInfo,
@@ -509,15 +568,24 @@ export const createKitchen = ({
509
568
  urlGraph.updateReferences(urlInfo, references)
510
569
 
511
570
  // "finalize" hook
512
- const finalizeReturnValue = await pluginController.callHooksUntil(
513
- "finalize",
514
- urlInfo,
515
- context,
516
- )
517
- await urlInfoTransformer.applyFinalTransformations(
518
- urlInfo,
519
- finalizeReturnValue,
520
- )
571
+ try {
572
+ const finalizeReturnValue = await pluginController.callAsyncHooksUntil(
573
+ "finalizeUrlContent",
574
+ urlInfo,
575
+ context,
576
+ )
577
+ await urlInfoTransformer.applyFinalTransformations(
578
+ urlInfo,
579
+ finalizeReturnValue,
580
+ )
581
+ } catch (error) {
582
+ throw createFinalizeUrlContentError({
583
+ pluginController,
584
+ reference,
585
+ urlInfo,
586
+ error,
587
+ })
588
+ }
521
589
 
522
590
  // "cooked" hook
523
591
  pluginController.callHooks(
@@ -541,7 +609,7 @@ export const createKitchen = ({
541
609
  },
542
610
  )
543
611
  }
544
- const cook = async ({ urlInfo, outDirectoryUrl, ...rest }) => {
612
+ const cook = memoizeCook(async ({ urlInfo, outDirectoryUrl, ...rest }) => {
545
613
  outDirectoryUrl = outDirectoryUrl ? String(outDirectoryUrl) : undefined
546
614
 
547
615
  const writeFiles = ({ gotError }) => {
@@ -576,19 +644,96 @@ export const createKitchen = ({
576
644
  writeFiles({ gotError: true })
577
645
  throw e
578
646
  }
579
- }
647
+ })
580
648
 
581
649
  baseContext.cook = cook
582
650
 
651
+ const prepareEntryPoint = (params) => {
652
+ const entryReference = createReference(params)
653
+ const entryUrlInfo = resolveReference(entryReference)
654
+ return [entryReference, entryUrlInfo]
655
+ }
656
+
657
+ const injectReference = (params) => {
658
+ const ref = createReference(params)
659
+ const urlInfo = resolveReference(ref)
660
+ return [ref, urlInfo]
661
+ }
662
+
583
663
  return {
584
664
  pluginController,
585
665
  urlInfoTransformer,
586
666
  rootDirectoryUrl,
587
667
  jsenvDirectoryUrl,
588
- isSupported,
589
- createReference,
590
- resolveReference,
668
+ baseContext,
591
669
  cook,
670
+ prepareEntryPoint,
671
+ injectReference,
672
+ }
673
+ }
674
+
675
+ const memoizeCook = (cook) => {
676
+ const pendingDishes = new Map()
677
+ return async (params) => {
678
+ const { urlInfo } = params
679
+ const { url, modifiedTimestamp } = urlInfo
680
+ const pendingDish = pendingDishes.get(url)
681
+ if (pendingDish) {
682
+ if (!modifiedTimestamp) {
683
+ await pendingDish.promise
684
+ return
685
+ }
686
+ if (pendingDish.timestamp > modifiedTimestamp) {
687
+ await pendingDish.promise
688
+ return
689
+ }
690
+ pendingDishes.delete(url)
691
+ }
692
+ const timestamp = Date.now()
693
+ const promise = cook(params)
694
+ pendingDishes.set(url, {
695
+ timestamp,
696
+ promise,
697
+ })
698
+ try {
699
+ await promise
700
+ } finally {
701
+ pendingDishes.delete(url)
702
+ }
703
+ }
704
+ }
705
+
706
+ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
707
+ Object.assign(urlInfo.data, reference.data)
708
+ Object.assign(urlInfo.timing, reference.timing)
709
+ if (reference.injected) {
710
+ urlInfo.data.injected = true
711
+ }
712
+ if (reference.filename) {
713
+ urlInfo.filename = reference.filename
714
+ }
715
+ if (reference.isInline) {
716
+ urlInfo.isInline = true
717
+ const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
718
+ urlInfo.inlineUrlSite = {
719
+ url: parentUrlInfo.url,
720
+ content: reference.isOriginalPosition
721
+ ? parentUrlInfo.originalContent
722
+ : parentUrlInfo.content,
723
+ line: reference.specifierLine,
724
+ column: reference.specifierColumn,
725
+ }
726
+ urlInfo.contentType = reference.contentType
727
+ urlInfo.originalContent =
728
+ context === "build"
729
+ ? urlInfo.originalContent === undefined
730
+ ? reference.content
731
+ : urlInfo.originalContent
732
+ : reference.content
733
+ urlInfo.content = reference.content
734
+ }
735
+ if (isWebWorkerEntryPointReference(reference)) {
736
+ urlInfo.data.isWebWorkerEntryPoint = true
592
737
  }
593
738
  }
594
739
 
@@ -626,54 +771,86 @@ const adjustUrlSite = (urlInfo, { urlGraph, url, line, column }) => {
626
771
  )
627
772
  }
628
773
 
629
- const inferUrlInfoType = ({ contentType }) => {
774
+ const inferUrlInfoType = ({ url, contentType }) => {
630
775
  if (contentType === "text/html") {
631
776
  return "html"
632
777
  }
633
778
  if (contentType === "text/css") {
634
779
  return "css"
635
780
  }
636
- if (contentType === "application/javascript") {
637
- return "js"
638
- }
639
- if (contentType === "application/json") {
640
- return "json"
781
+ if (contentType === "text/javascript") {
782
+ const urlObject = new URL(url)
783
+ if (urlObject.searchParams.has("js_classic")) {
784
+ return "js_classic"
785
+ }
786
+ return "js_module"
641
787
  }
642
788
  if (contentType === "application/importmap+json") {
643
789
  return "importmap"
644
790
  }
791
+ if (contentType === "application/manifest+json") {
792
+ return "webmanifest"
793
+ }
794
+ if (contentType === "image/svg+xml") {
795
+ return "svg"
796
+ }
797
+ if (CONTENT_TYPE.isJson(contentType)) {
798
+ return "json"
799
+ }
800
+ if (CONTENT_TYPE.isTextual(contentType)) {
801
+ return "text"
802
+ }
645
803
  return "other"
646
804
  }
647
805
 
648
- const determineFileUrlForOutDirectory = ({
649
- rootDirectoryUrl,
650
- outDirectoryUrl,
651
- url,
652
- }) => {
653
- if (!outDirectoryUrl) {
654
- return url
806
+ const inferUrlInfoSubtype = ({ type, subtype, url }) => {
807
+ if (type === "js_classic" || type === "js_module") {
808
+ const urlObject = new URL(url)
809
+ if (urlObject.searchParams.has("worker")) {
810
+ return "worker"
811
+ }
812
+ if (urlObject.searchParams.has("service_worker")) {
813
+ return "service_worker"
814
+ }
815
+ if (urlObject.searchParams.has("shared_worker")) {
816
+ return "shared_worker"
817
+ }
818
+ // if we are currently inside a worker, all deps are consider inside worker too
819
+ return subtype
820
+ }
821
+ return ""
822
+ }
823
+
824
+ const determineFileUrlForOutDirectory = ({ urlInfo, context }) => {
825
+ if (!context.outDirectoryUrl) {
826
+ return urlInfo.url
827
+ }
828
+ if (!urlInfo.url.startsWith("file:")) {
829
+ return urlInfo.url
655
830
  }
656
- if (!url.startsWith("file:")) {
657
- return url
831
+ let url = urlInfo.url
832
+ if (!urlIsInsideOf(urlInfo.url, context.rootDirectoryUrl)) {
833
+ const fsRootUrl = ensureWindowsDriveLetter("file:///", urlInfo.url)
834
+ url = `${context.rootDirectoryUrl}@fs/${url.slice(fsRootUrl.length)}`
658
835
  }
659
- if (!urlIsInsideOf(url, rootDirectoryUrl)) {
660
- url = `${rootDirectoryUrl}@fs/${url.slice(fileSystemRootUrl.length)}`
836
+ if (urlInfo.filename) {
837
+ url = setUrlFilename(url, urlInfo.filename)
661
838
  }
662
839
  return moveUrl({
663
- url: fileUrlConverter.asUrlWithoutSpecialParams(url),
664
- from: rootDirectoryUrl,
665
- to: outDirectoryUrl,
840
+ url,
841
+ from: context.rootDirectoryUrl,
842
+ to: context.outDirectoryUrl,
666
843
  preferAbsolute: true,
667
844
  })
668
845
  }
669
846
 
670
- const specifierFormat = {
847
+ const urlSpecifierFormat = {
671
848
  encode: (reference) => {
672
849
  const { generatedSpecifier } = reference
673
850
  if (generatedSpecifier.then) {
674
851
  return generatedSpecifier.then((value) => {
675
852
  reference.generatedSpecifier = value
676
- return specifierFormat.encode(reference)
853
+ return urlSpecifierFormat.encode(reference)
677
854
  })
678
855
  }
679
856
  // allow plugin to return a function to bypas default formatting
@@ -698,10 +875,11 @@ const specifierFormat = {
698
875
  },
699
876
  }
700
877
  const formatters = {
701
- js_import_export: { encode: JSON.stringify, decode: JSON.parse },
702
- js_import_meta_url_pattern: { encode: JSON.stringify, decode: JSON.parse },
878
+ "js_import_export": { encode: JSON.stringify, decode: JSON.parse },
879
+ "js_url_specifier": { encode: JSON.stringify, decode: JSON.parse },
880
+ "css_@import": { encode: JSON.stringify, code: JSON.stringify },
703
881
  // https://github.com/webpack-contrib/css-loader/pull/627/files
704
- css_url: {
882
+ "css_url": {
705
883
  encode: (url) => {
706
884
  // If url is already wrapped in quotes, remove them
707
885
  url = formatters.css_url.decode(url)