@jsenv/core 28.1.3 → 28.2.2
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.
- package/dist/js/script_type_module_supervisor.js +8 -13
- package/dist/js/supervisor.js +690 -504
- package/dist/main.js +13332 -13179
- package/package.json +5 -5
- package/readme.md +3 -3
- package/src/build/build.js +980 -713
- package/src/build/inject_global_version_mappings.js +5 -20
- package/src/build/start_build_server.js +2 -2
- package/src/dev/start_dev_server.js +6 -3
- package/src/omega/compat/runtime_compat.js +9 -6
- package/src/omega/errors.js +3 -0
- package/src/omega/fetched_content_compliance.js +2 -2
- package/src/omega/kitchen.js +191 -146
- package/src/omega/server/file_service.js +104 -71
- package/src/omega/url_graph/url_graph_loader.js +77 -0
- package/src/omega/url_graph/url_info_transformations.js +12 -15
- package/src/omega/url_graph.js +118 -101
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +34 -36
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +3 -2
- package/src/plugins/bundling/js_module/{bundle_js_module.js → bundle_js_modules.js} +51 -14
- package/src/plugins/bundling/jsenv_plugin_bundling.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +11 -0
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +73 -62
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +77 -89
- package/src/plugins/plugin_controller.js +26 -22
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +1 -0
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +7 -9
- package/src/plugins/supervisor/client/supervisor.js +99 -52
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +2 -4
- package/src/plugins/transpilation/as_js_classic/async-to-promises.js +16 -0
- package/src/plugins/transpilation/as_js_classic/convert_js_module_to_js_classic.js +85 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +48 -190
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_conversion.js +104 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +161 -240
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_library.js +92 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_workers.js +19 -12
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -24
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +82 -52
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +12 -13
- package/src/plugins/url_analysis/html/html_urls.js +91 -34
- package/src/plugins/url_analysis/js/js_urls.js +5 -4
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +1 -0
- package/src/test/execute_plan.js +3 -8
- package/src/build/inject_service_worker_urls.js +0 -78
- package/src/build/resync_resource_hints.js +0 -112
- 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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
84
|
+
ref.subtype === rel,
|
|
208
85
|
)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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,92 @@
|
|
|
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
|
+
babelHelpersChunk: false,
|
|
56
|
+
preserveDynamicImport: true,
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
const jsModuleBundledUrlInfo = bundleUrlInfos[jsModuleUrlInfo.url]
|
|
60
|
+
if (context.scenarios.dev) {
|
|
61
|
+
jsModuleBundledUrlInfo.sourceUrls.forEach((sourceUrl) => {
|
|
62
|
+
context.referenceUtils.inject({
|
|
63
|
+
type: "js_url_specifier",
|
|
64
|
+
specifier: sourceUrl,
|
|
65
|
+
isImplicit: true,
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
} else if (context.scenarios.build) {
|
|
69
|
+
jsModuleBundledUrlInfo.sourceUrls.forEach((sourceUrl) => {
|
|
70
|
+
const sourceUrlInfo = context.urlGraph.getUrlInfo(sourceUrl)
|
|
71
|
+
if (sourceUrlInfo.dependents.size === 0) {
|
|
72
|
+
context.urlGraph.deleteUrlInfo(sourceUrl)
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
const { content, sourcemap } = await convertJsModuleToJsClassic({
|
|
77
|
+
systemJsInjection,
|
|
78
|
+
systemJsClientFileUrl,
|
|
79
|
+
urlInfo,
|
|
80
|
+
jsModuleUrlInfo: jsModuleBundledUrlInfo,
|
|
81
|
+
})
|
|
82
|
+
return {
|
|
83
|
+
content,
|
|
84
|
+
contentType: "text/javascript",
|
|
85
|
+
type: "js_classic",
|
|
86
|
+
originalUrl: urlInfo.originalUrl,
|
|
87
|
+
originalContent: jsModuleUrlInfo.originalContent,
|
|
88
|
+
sourcemap,
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}
|