@jsenv/core 28.1.2 → 28.2.1

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 (49) hide show
  1. package/dist/js/script_type_module_supervisor.js +8 -13
  2. package/dist/js/supervisor.js +690 -504
  3. package/dist/main.js +13384 -13228
  4. package/package.json +6 -6
  5. package/readme.md +3 -3
  6. package/src/build/build.js +980 -713
  7. package/src/build/inject_global_version_mappings.js +5 -20
  8. package/src/build/start_build_server.js +2 -2
  9. package/src/dev/start_dev_server.js +6 -3
  10. package/src/execute/run.js +1 -1
  11. package/src/omega/compat/runtime_compat.js +9 -6
  12. package/src/omega/errors.js +3 -0
  13. package/src/omega/fetched_content_compliance.js +2 -2
  14. package/src/omega/kitchen.js +191 -146
  15. package/src/omega/server/file_service.js +104 -71
  16. package/src/omega/url_graph/url_graph_loader.js +77 -0
  17. package/src/omega/url_graph/url_info_transformations.js +12 -15
  18. package/src/omega/url_graph.js +118 -101
  19. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -0
  20. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +34 -36
  21. package/src/plugins/autoreload/jsenv_plugin_hmr.js +3 -2
  22. package/src/plugins/bundling/js_module/{bundle_js_module.js → bundle_js_modules.js} +51 -14
  23. package/src/plugins/bundling/jsenv_plugin_bundling.js +2 -2
  24. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +11 -0
  25. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +73 -62
  26. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +77 -89
  27. package/src/plugins/plugin_controller.js +26 -22
  28. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +1 -0
  29. package/src/plugins/supervisor/client/script_type_module_supervisor.js +7 -9
  30. package/src/plugins/supervisor/client/supervisor.js +99 -52
  31. package/src/plugins/supervisor/jsenv_plugin_supervisor.js +2 -4
  32. package/src/plugins/transpilation/as_js_classic/async-to-promises.js +16 -0
  33. package/src/plugins/transpilation/as_js_classic/convert_js_module_to_js_classic.js +85 -0
  34. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +48 -190
  35. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_conversion.js +104 -0
  36. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +161 -240
  37. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_library.js +91 -0
  38. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_workers.js +19 -12
  39. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -24
  40. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +82 -52
  41. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +12 -13
  42. package/src/plugins/url_analysis/html/html_urls.js +91 -34
  43. package/src/plugins/url_analysis/js/js_urls.js +5 -4
  44. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +1 -0
  45. package/src/test/execute_plan.js +3 -8
  46. package/src/test/execute_test_plan.js +1 -1
  47. package/src/build/inject_service_worker_urls.js +0 -78
  48. package/src/build/resync_resource_hints.js +0 -112
  49. package/src/omega/url_graph/url_graph_load.js +0 -74
@@ -0,0 +1,104 @@
1
+ /*
2
+ * - propagate ?as_js_classic to urls
3
+ * - perform conversion from js module to js classic when url uses ?as_js_classic
4
+ */
5
+
6
+ import { injectQueryParams } from "@jsenv/urls"
7
+ import { convertJsModuleToJsClassic } from "./convert_js_module_to_js_classic.js"
8
+
9
+ export const jsenvPluginAsJsClassicConversion = ({
10
+ systemJsInjection,
11
+ systemJsClientFileUrl,
12
+ generateJsClassicFilename,
13
+ }) => {
14
+ const shouldPropagateJsClassic = (reference, context) => {
15
+ const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
16
+ if (!parentUrlInfo) {
17
+ return false
18
+ }
19
+ return new URL(parentUrlInfo.url).searchParams.has("as_js_classic")
20
+ }
21
+ const markAsJsClassicProxy = (reference) => {
22
+ reference.expectedType = "js_classic"
23
+ reference.filename = generateJsClassicFilename(reference.url)
24
+ }
25
+ const turnIntoJsClassicProxy = (reference) => {
26
+ const urlTransformed = injectQueryParams(reference.url, {
27
+ as_js_classic: "",
28
+ })
29
+ markAsJsClassicProxy(reference)
30
+ return urlTransformed
31
+ }
32
+
33
+ return {
34
+ name: "jsenv:as_js_classic_conversion",
35
+ appliesDuring: "*",
36
+ redirectUrl: (reference, context) => {
37
+ if (reference.searchParams.has("as_js_classic")) {
38
+ markAsJsClassicProxy(reference)
39
+ return null
40
+ }
41
+ if (
42
+ reference.type === "js_import_export" ||
43
+ reference.subtype === "system_register_arg" ||
44
+ reference.subtype === "system_import_arg"
45
+ ) {
46
+ // We want to propagate transformation of js module to js classic to:
47
+ // - import specifier (static/dynamic import + re-export)
48
+ // - url specifier when inside System.register/_context.import()
49
+ // (because it's the transpiled equivalent of static and dynamic imports)
50
+ // And not other references otherwise we could try to transform inline resources
51
+ // or specifiers inside new URL()...
52
+ if (shouldPropagateJsClassic(reference, context)) {
53
+ return turnIntoJsClassicProxy(reference, context)
54
+ }
55
+ }
56
+ return null
57
+ },
58
+ fetchUrlContent: async (urlInfo, context) => {
59
+ const [jsModuleReference, jsModuleUrlInfo] =
60
+ context.getWithoutSearchParam({
61
+ urlInfo,
62
+ context,
63
+ searchParam: "as_js_classic",
64
+ // override the expectedType to "js_module"
65
+ // because when there is ?as_js_classic it means the underlying resource
66
+ // is a js_module
67
+ expectedType: "js_module",
68
+ })
69
+ if (!jsModuleReference) {
70
+ return null
71
+ }
72
+ await context.fetchUrlContent(jsModuleUrlInfo, {
73
+ reference: jsModuleReference,
74
+ })
75
+ if (context.scenarios.dev) {
76
+ context.referenceUtils.found({
77
+ type: "js_import_export",
78
+ subtype: jsModuleReference.subtype,
79
+ specifier: jsModuleReference.url,
80
+ expectedType: "js_module",
81
+ })
82
+ } else if (
83
+ context.scenarios.build &&
84
+ jsModuleUrlInfo.dependents.size === 0
85
+ ) {
86
+ context.urlGraph.deleteUrlInfo(jsModuleUrlInfo.url)
87
+ }
88
+ const { content, sourcemap } = await convertJsModuleToJsClassic({
89
+ systemJsInjection,
90
+ systemJsClientFileUrl,
91
+ urlInfo,
92
+ jsModuleUrlInfo,
93
+ })
94
+ return {
95
+ content,
96
+ contentType: "text/javascript",
97
+ type: "js_classic",
98
+ originalUrl: jsModuleUrlInfo.originalUrl,
99
+ originalContent: jsModuleUrlInfo.originalContent,
100
+ sourcemap,
101
+ }
102
+ },
103
+ }
104
+ }
@@ -1,285 +1,206 @@
1
- import {
2
- generateInlineContentUrl,
3
- injectQueryParamsIntoSpecifier,
4
- } from "@jsenv/urls"
1
+ /*
2
+ * when <script type="module"> cannot be used:
3
+ * - ?as_js_classic is injected into the src of <script type="module">
4
+ * - js inside <script type="module"> is transformed into classic js
5
+ * - <link rel="modulepreload"> are converted to <link rel="preload">
6
+ */
7
+
5
8
  import {
6
9
  parseHtmlString,
7
10
  visitHtmlNodes,
8
11
  stringifyHtmlAst,
9
12
  getHtmlNodeAttribute,
10
- getHtmlNodeText,
11
- getHtmlNodePosition,
12
13
  setHtmlNodeAttributes,
13
- setHtmlNodeText,
14
14
  analyzeScriptNode,
15
15
  injectScriptNodeAsEarlyAsPossible,
16
16
  createHtmlNode,
17
17
  } from "@jsenv/ast"
18
+ import { injectQueryParams } from "@jsenv/urls"
18
19
 
19
20
  export const jsenvPluginAsJsClassicHtml = ({
20
21
  systemJsInjection,
21
22
  systemJsClientFileUrl,
22
- generateJsClassicFilename,
23
23
  }) => {
24
+ let shouldTransformScriptTypeModule
25
+
26
+ const turnIntoJsClassicProxy = (reference) => {
27
+ return injectQueryParams(reference.url, { as_js_classic: "" })
28
+ }
29
+
24
30
  return {
25
31
  name: "jsenv:as_js_classic_html",
26
32
  appliesDuring: "*",
27
- transformUrlContent: {
28
- html: async (urlInfo, context) => {
29
- const shouldTransformScriptTypeModule =
30
- !context.isSupportedOnCurrentClients("script_type_module") ||
31
- !context.isSupportedOnCurrentClients("import_dynamic") ||
32
- !context.isSupportedOnCurrentClients("import_meta")
33
- const htmlAst = parseHtmlString(urlInfo.content)
34
- const preloadAsScriptNodes = []
35
- const modulePreloadNodes = []
36
- const moduleScriptNodes = []
37
- const classicScriptNodes = []
38
- const visitLinkNodes = (node) => {
39
- const rel = getHtmlNodeAttribute(node, "rel")
40
- if (rel === "modulepreload") {
41
- modulePreloadNodes.push(node)
42
- return
43
- }
44
- if (rel === "preload") {
45
- const asValue = getHtmlNodeAttribute(node, "as")
46
- if (asValue === "script") {
47
- preloadAsScriptNodes.push(node)
48
- }
49
- return
50
- }
33
+ init: (context) => {
34
+ shouldTransformScriptTypeModule =
35
+ !context.isSupportedOnCurrentClients("script_type_module") ||
36
+ !context.isSupportedOnCurrentClients("import_dynamic") ||
37
+ !context.isSupportedOnCurrentClients("import_meta")
38
+ },
39
+ redirectUrl: {
40
+ link_href: (reference) => {
41
+ if (
42
+ shouldTransformScriptTypeModule &&
43
+ reference.subtype === "modulepreload"
44
+ ) {
45
+ return turnIntoJsClassicProxy(reference)
51
46
  }
52
- const visitScriptNodes = (node) => {
53
- const { type } = analyzeScriptNode(node)
54
- if (type === "js_module") {
55
- moduleScriptNodes.push(node)
56
- return
57
- }
58
- if (type === "js_classic") {
59
- classicScriptNodes.push(node)
60
- return
61
- }
47
+ if (
48
+ shouldTransformScriptTypeModule &&
49
+ reference.subtype === "preload" &&
50
+ reference.expectedType === "js_module"
51
+ ) {
52
+ return turnIntoJsClassicProxy(reference)
53
+ }
54
+ return null
55
+ },
56
+ script_src: (reference) => {
57
+ if (
58
+ shouldTransformScriptTypeModule &&
59
+ reference.expectedType === "js_module"
60
+ ) {
61
+ return turnIntoJsClassicProxy(reference)
62
62
  }
63
+ return null
64
+ },
65
+ },
66
+ finalizeUrlContent: {
67
+ html: async (urlInfo, context) => {
68
+ const htmlAst = parseHtmlString(urlInfo.content)
69
+ const mutations = []
63
70
  visitHtmlNodes(htmlAst, {
64
71
  link: (node) => {
65
- visitLinkNodes(node)
66
- },
67
- script: (node) => {
68
- visitScriptNodes(node)
69
- },
70
- })
71
-
72
- const actions = []
73
- const jsModuleUrls = []
74
- const convertedUrls = []
75
- const getReferenceAsJsClassic = async (
76
- reference,
77
- {
78
- // we don't cook resource hints
79
- // because they might refer to resource that will be modified during build
80
- // It also means something else HAVE to reference that url in order to cook it
81
- // so that the preload is deleted by "resync_resource_hints.js" otherwise
82
- cookIt = false,
83
- } = {},
84
- ) => {
85
- const newReferenceProps = {
86
- expectedType: "js_classic",
87
- specifier: injectQueryParamsIntoSpecifier(reference.specifier, {
88
- as_js_classic: "",
89
- }),
90
- filename: generateJsClassicFilename(reference.url),
91
- }
92
- const [newReference, newUrlInfo] = context.referenceUtils.update(
93
- reference,
94
- newReferenceProps,
95
- )
96
- const convertedUrl = newUrlInfo.url
97
- if (!convertedUrls.includes(convertedUrl)) {
98
- convertedUrls.push(convertedUrl)
99
- }
100
- if (cookIt) {
101
- // during dev it means js modules will be cooked before server sends the HTML
102
- // it's ok because:
103
- // - during dev script_type_module are supported (dev use a recent browser)
104
- // - even if browser is not supported it still works it's jus a bit slower
105
- // because it needs to decide if systemjs will be injected or not
106
- await context.cook(newUrlInfo, { reference: newReference })
107
- }
108
- return [newReference, newUrlInfo]
109
- }
110
-
111
- classicScriptNodes.forEach((classicScriptNode) => {
112
- const src = getHtmlNodeAttribute(classicScriptNode, "src")
113
- if (src !== undefined) {
114
- const reference = urlInfo.references.find(
115
- (ref) =>
116
- ref.generatedSpecifier === src && ref.type === "script_src",
117
- )
118
- const urlObject = new URL(reference.url)
119
- if (urlObject.searchParams.has("as_js_classic")) {
120
- const convertedUrl = urlObject.href
121
- convertedUrls.push(convertedUrl)
122
- urlObject.searchParams.delete("as_js_classic")
123
- const jsModuleUrl = urlObject.href
124
- jsModuleUrls.push(jsModuleUrl)
125
- actions.push(async () => {
126
- const urlInfo = context.urlGraph.getUrlInfo(convertedUrl)
127
- await context.cook(urlInfo, { reference })
128
- })
72
+ const rel = getHtmlNodeAttribute(node, "rel")
73
+ if (rel !== "modulepreload" && rel !== "preload") {
74
+ return
129
75
  }
130
- }
131
- })
132
- moduleScriptNodes.forEach((moduleScriptNode) => {
133
- const src = getHtmlNodeAttribute(moduleScriptNode, "src")
134
- if (src !== undefined) {
135
- const reference = urlInfo.references.find(
136
- (ref) =>
137
- ref.generatedSpecifier === src &&
138
- ref.type === "script_src" &&
139
- ref.expectedType === "js_module",
140
- )
141
- jsModuleUrls.push(reference.url)
142
- if (shouldTransformScriptTypeModule) {
143
- actions.push(async () => {
144
- const [newReference] = await getReferenceAsJsClassic(
145
- reference,
146
- {
147
- cookIt: true,
148
- },
149
- )
150
- setHtmlNodeAttributes(moduleScriptNode, {
151
- type: undefined,
152
- src: newReference.generatedSpecifier,
153
- })
154
- })
76
+ const href = getHtmlNodeAttribute(node, "href")
77
+ if (!href) {
78
+ return
155
79
  }
156
- return
157
- }
158
- if (shouldTransformScriptTypeModule) {
159
- const htmlNodeText = getHtmlNodeText(moduleScriptNode)
160
- actions.push(async () => {
161
- const { line, column, lineEnd, columnEnd, isOriginal } =
162
- getHtmlNodePosition(moduleScriptNode, {
163
- preferOriginal: true,
164
- })
165
- let inlineScriptUrl = generateInlineContentUrl({
166
- url: urlInfo.url,
167
- extension: ".js",
168
- line,
169
- column,
170
- lineEnd,
171
- columnEnd,
172
- })
173
- const [inlineReference] = context.referenceUtils.foundInline({
174
- node: moduleScriptNode,
175
- type: "script_src",
176
- expectedType: "js_module",
177
- isOriginalPosition: isOriginal,
178
- // we remove 1 to the line because imagine the following html:
179
- // <script>console.log('ok')</script>
180
- // -> content starts same line as <script>
181
- specifierLine: line - 1,
182
- specifierColumn: column,
183
- specifier: inlineScriptUrl,
184
- contentType: "text/javascript",
185
- content: htmlNodeText,
186
- })
187
- const [, newUrlInfo] = await getReferenceAsJsClassic(
188
- inlineReference,
189
- { cookIt: true },
190
- )
191
- setHtmlNodeText(moduleScriptNode, newUrlInfo.content)
192
- setHtmlNodeAttributes(moduleScriptNode, {
193
- "type": undefined,
194
- "jsenv-plugin-owner": "jsenv:as_js_classic_html",
195
- "jsenv-plugin-action": "content_cooked",
196
- })
197
- })
198
- }
199
- })
200
- if (shouldTransformScriptTypeModule) {
201
- preloadAsScriptNodes.forEach((preloadAsScriptNode) => {
202
- const href = getHtmlNodeAttribute(preloadAsScriptNode, "href")
203
- const reference = urlInfo.references.find(
80
+ const reference = context.referenceUtils.find(
204
81
  (ref) =>
205
82
  ref.generatedSpecifier === href &&
206
83
  ref.type === "link_href" &&
207
- ref.expectedType === undefined,
84
+ ref.subtype === rel,
208
85
  )
209
- const expectedScriptType = jsModuleUrls.includes(reference.url)
210
- ? "module"
211
- : "classic"
212
- if (expectedScriptType === "module") {
213
- actions.push(async () => {
214
- // reference modified by <script type="module"> conversion
215
- let newReference
216
- if (reference.next) {
217
- newReference = reference.next
218
- } else {
219
- // when the url is not referenced by a <script type="module">
220
- // we assume we want to preload "classic" but it might not be the case
221
- // but it's unlikely to happen and people should use "modulepreload" in that case anyway
222
- ;[newReference] = await getReferenceAsJsClassic(reference)
223
- }
224
- setHtmlNodeAttributes(preloadAsScriptNode, {
225
- href: newReference.generatedSpecifier,
86
+ if (!isOrWasExpectingJsModule(reference)) {
87
+ return
88
+ }
89
+ if (rel === "modulepreload") {
90
+ mutations.push(() => {
91
+ setHtmlNodeAttributes(node, {
92
+ rel: "preload",
93
+ as: "script",
226
94
  crossorigin: undefined,
227
95
  })
228
96
  })
229
97
  }
230
- })
231
- modulePreloadNodes.forEach((modulePreloadNode) => {
232
- const href = getHtmlNodeAttribute(modulePreloadNode, "href")
233
- const reference = urlInfo.references.find(
234
- (ref) =>
235
- ref.generatedSpecifier === href &&
236
- ref.type === "link_href" &&
237
- ref.expectedType === "js_module",
238
- )
239
- actions.push(async () => {
240
- let newReference
241
- if (reference.next) {
242
- newReference = reference.next
243
- } else {
244
- ;[newReference] = await getReferenceAsJsClassic(reference)
98
+ if (rel === "preload") {
99
+ mutations.push(() => {
100
+ setHtmlNodeAttributes(node, { crossorigin: undefined })
101
+ })
102
+ }
103
+ },
104
+ script: (node) => {
105
+ const { type } = analyzeScriptNode(node)
106
+ if (type !== "js_module") {
107
+ return
108
+ }
109
+ const src = getHtmlNodeAttribute(node, "src")
110
+ if (src) {
111
+ const reference = context.referenceUtils.find(
112
+ (ref) =>
113
+ ref.generatedSpecifier === src &&
114
+ ref.type === "script_src" &&
115
+ ref.subtype === "js_module",
116
+ )
117
+ if (!reference) {
118
+ return
119
+ }
120
+ if (reference.expectedType === "js_classic") {
121
+ mutations.push(() => {
122
+ setHtmlNodeAttributes(node, { type: undefined })
123
+ })
245
124
  }
246
- setHtmlNodeAttributes(modulePreloadNode, {
247
- rel: "preload",
248
- as: "script",
249
- href: newReference.generatedSpecifier,
125
+ } else if (shouldTransformScriptTypeModule) {
126
+ mutations.push(() => {
127
+ setHtmlNodeAttributes(node, { type: undefined })
250
128
  })
251
- })
252
- })
253
- }
129
+ }
130
+ },
131
+ })
254
132
 
255
- if (actions.length === 0) {
256
- return null
257
- }
258
- await Promise.all(actions.map((action) => action()))
259
133
  if (systemJsInjection) {
260
- const needsSystemJs = convertedUrls.some(
261
- (convertedUrl) =>
262
- context.urlGraph.getUrlInfo(convertedUrl).data.jsClassicFormat ===
263
- "system",
264
- )
134
+ let needsSystemJs = false
135
+ for (const reference of urlInfo.references) {
136
+ if (reference.isResourceHint) {
137
+ // we don't cook resource hints
138
+ // because they might refer to resource that will be modified during build
139
+ // It also means something else HAVE to reference that url in order to cook it
140
+ // so that the preload is deleted by "resync_resource_hints.js" otherwise
141
+ continue
142
+ }
143
+ if (isOrWasExpectingJsModule(reference)) {
144
+ const dependencyUrlInfo = context.urlGraph.getUrlInfo(
145
+ reference.url,
146
+ )
147
+ try {
148
+ await context.cook(dependencyUrlInfo, { reference })
149
+ if (dependencyUrlInfo.data.jsClassicFormat === "system") {
150
+ needsSystemJs = true
151
+ break
152
+ }
153
+ } catch (e) {
154
+ if (context.scenarios.dev) {
155
+ // ignore cooking error, the browser will trigger it again on fetch
156
+ } else {
157
+ throw e
158
+ }
159
+ }
160
+ }
161
+ }
265
162
  if (needsSystemJs) {
266
- const [systemJsReference] = context.referenceUtils.inject({
267
- type: "script_src",
268
- expectedType: "js_classic",
269
- specifier: systemJsClientFileUrl,
163
+ mutations.push(() => {
164
+ const [systemJsReference] = context.referenceUtils.inject({
165
+ type: "script_src",
166
+ expectedType: "js_classic",
167
+ specifier: systemJsClientFileUrl,
168
+ })
169
+ injectScriptNodeAsEarlyAsPossible(
170
+ htmlAst,
171
+ createHtmlNode({
172
+ tagName: "script",
173
+ src: systemJsReference.generatedSpecifier,
174
+ }),
175
+ "jsenv:as_js_classic_html",
176
+ )
270
177
  })
271
- injectScriptNodeAsEarlyAsPossible(
272
- htmlAst,
273
- createHtmlNode({
274
- tagName: "script",
275
- src: systemJsReference.generatedSpecifier,
276
- }),
277
- "jsenv:as_js_classic_html",
278
- )
279
178
  }
280
179
  }
180
+ if (mutations.length === 0) {
181
+ return null
182
+ }
183
+ mutations.forEach((mutation) => mutation())
281
184
  return stringifyHtmlAst(htmlAst)
282
185
  },
283
186
  },
284
187
  }
285
188
  }
189
+
190
+ const isOrWasExpectingJsModule = (reference) => {
191
+ if (isExpectingJsModule(reference)) {
192
+ return true
193
+ }
194
+ if (reference.original && isExpectingJsModule(reference.original)) {
195
+ return true
196
+ }
197
+ return false
198
+ }
199
+
200
+ const isExpectingJsModule = (reference) => {
201
+ return (
202
+ reference.expectedType === "js_module" ||
203
+ reference.searchParams.has("as_js_classic") ||
204
+ reference.searchParams.has("as_js_classic_library")
205
+ )
206
+ }
@@ -0,0 +1,91 @@
1
+ import { createUrlGraphLoader } from "@jsenv/core/src/omega/url_graph/url_graph_loader.js"
2
+ import { bundleJsModules } from "@jsenv/core/src/plugins/bundling/js_module/bundle_js_modules.js"
3
+
4
+ import { convertJsModuleToJsClassic } from "./convert_js_module_to_js_classic.js"
5
+
6
+ export const jsenvPluginAsJsClassicLibrary = ({
7
+ systemJsInjection,
8
+ systemJsClientFileUrl,
9
+ generateJsClassicFilename,
10
+ }) => {
11
+ const markAsJsClassicLibraryProxy = (reference) => {
12
+ reference.expectedType = "js_classic"
13
+ reference.filename = generateJsClassicFilename(reference.url)
14
+ }
15
+
16
+ return {
17
+ name: "jsenv:as_js_classic_library",
18
+ appliesDuring: "*",
19
+ redirectUrl: (reference) => {
20
+ if (reference.searchParams.has("as_js_classic_library")) {
21
+ markAsJsClassicLibraryProxy(reference)
22
+ }
23
+ },
24
+ fetchUrlContent: async (urlInfo, context) => {
25
+ const [jsModuleReference, jsModuleUrlInfo] =
26
+ context.getWithoutSearchParam({
27
+ urlInfo,
28
+ context,
29
+ searchParam: "as_js_classic_library",
30
+ // override the expectedType to "js_module"
31
+ // because when there is ?as_js_classic_library it means the underlying resource
32
+ // is a js_module
33
+ expectedType: "js_module",
34
+ })
35
+ if (!jsModuleReference) {
36
+ return null
37
+ }
38
+ // cook it to get content + dependencies
39
+ await context.cook(jsModuleUrlInfo, { reference: jsModuleReference })
40
+ const loader = createUrlGraphLoader(context)
41
+ loader.loadReferencedUrlInfos(jsModuleUrlInfo, {
42
+ // we ignore dynamic import to cook lazyly (as browser request the server)
43
+ // these dynamic imports must inherit "?as_js_classic_library"
44
+ // This is done inside rollup for convenience
45
+ ignoreDynamicImport: true,
46
+ })
47
+ await loader.getAllLoadDonePromise()
48
+ const bundleUrlInfos = await bundleJsModules({
49
+ jsModuleUrlInfos: [jsModuleUrlInfo],
50
+ context: {
51
+ ...context,
52
+ buildDirectoryUrl: context.outDirectoryUrl,
53
+ },
54
+ options: {
55
+ preserveDynamicImport: true,
56
+ },
57
+ })
58
+ const jsModuleBundledUrlInfo = bundleUrlInfos[jsModuleUrlInfo.url]
59
+ if (context.scenarios.dev) {
60
+ jsModuleBundledUrlInfo.sourceUrls.forEach((sourceUrl) => {
61
+ context.referenceUtils.inject({
62
+ type: "js_url_specifier",
63
+ specifier: sourceUrl,
64
+ isImplicit: true,
65
+ })
66
+ })
67
+ } else if (context.scenarios.build) {
68
+ jsModuleBundledUrlInfo.sourceUrls.forEach((sourceUrl) => {
69
+ const sourceUrlInfo = context.urlGraph.getUrlInfo(sourceUrl)
70
+ if (sourceUrlInfo.dependents.size === 0) {
71
+ context.urlGraph.deleteUrlInfo(sourceUrl)
72
+ }
73
+ })
74
+ }
75
+ const { content, sourcemap } = await convertJsModuleToJsClassic({
76
+ systemJsInjection,
77
+ systemJsClientFileUrl,
78
+ urlInfo,
79
+ jsModuleUrlInfo: jsModuleBundledUrlInfo,
80
+ })
81
+ return {
82
+ content,
83
+ contentType: "text/javascript",
84
+ type: "js_classic",
85
+ originalUrl: urlInfo.originalUrl,
86
+ originalContent: jsModuleUrlInfo.originalContent,
87
+ sourcemap,
88
+ }
89
+ },
90
+ }
91
+ }