@jsenv/core 25.0.0 → 25.2.0
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/browser_runtime/browser_runtime_91c5a3b8.js.map +2 -2
- package/dist/build_manifest.js +4 -4
- package/dist/compile_proxy/asset-manifest.json +2 -2
- package/dist/compile_proxy/{compile_proxy_e3b0c442_809f35f7.js.map → compile_proxy.html__inline__20_809f35f7.js.map} +0 -0
- package/dist/compile_proxy/{compile_proxy_7ad5faa6.html → compile_proxy_8dfaee51.html} +3 -4
- package/dist/redirector/asset-manifest.json +2 -2
- package/dist/redirector/{redirector_e3b0c442_e391410e.js.map → redirector.html__inline__15_e391410e.js.map} +0 -0
- package/dist/redirector/{redirector_eb92e8a7.html → redirector_3e9a97b9.html} +3 -4
- package/dist/toolbar/asset-manifest.json +1 -1
- package/dist/toolbar/{toolbar_f7b8a263.html → toolbar_361afb84.html} +2 -3
- package/dist/toolbar_injector/asset-manifest.json +2 -2
- package/dist/toolbar_injector/{toolbar_injector_49e4756e.js → toolbar_injector_fac1e995.js} +2 -2
- package/dist/toolbar_injector/{toolbar_injector_49e4756e.js.map → toolbar_injector_fac1e995.js.map} +2 -2
- package/package.json +8 -8
- package/readme.md +61 -52
- package/src/buildProject.js +21 -13
- package/src/commonJsToJavaScriptModule.js +8 -7
- package/src/execute.js +2 -0
- package/src/executeTestPlan.js +14 -0
- package/src/internal/building/buildUsingRollup.js +4 -2
- package/src/internal/building/build_stats.js +3 -0
- package/src/internal/building/build_url_generator.js +153 -0
- package/src/internal/building/css/parseCssRessource.js +32 -26
- package/src/internal/building/html/parseHtmlRessource.js +109 -91
- package/src/internal/building/js/parseJsRessource.js +5 -13
- package/src/internal/building/parseRessource.js +3 -0
- package/src/internal/building/ressource_builder.js +72 -64
- package/src/internal/building/ressource_builder_util.js +17 -5
- package/src/internal/building/rollup_plugin_jsenv.js +262 -189
- package/src/internal/building/url_fetcher.js +16 -7
- package/src/internal/building/url_loader.js +1 -5
- package/src/internal/building/url_versioning.js +0 -173
- package/src/internal/compiling/babel_plugin_import_metadata.js +7 -11
- package/src/internal/compiling/babel_plugin_proxy_external_imports.js +31 -0
- package/src/internal/compiling/compile-directory/compile-asset.js +8 -4
- package/src/internal/compiling/compile-directory/getOrGenerateCompiledFile.js +43 -8
- package/src/internal/compiling/compile-directory/updateMeta.js +2 -8
- package/src/internal/compiling/compile-directory/validateCache.js +1 -2
- package/src/internal/compiling/compileFile.js +22 -10
- package/src/internal/compiling/compileHtml.js +15 -28
- package/src/internal/compiling/createCompiledFileService.js +22 -24
- package/src/internal/compiling/html_source_file_service.js +18 -19
- package/src/internal/compiling/js-compilation-service/jsenvTransform.js +14 -4
- package/src/internal/compiling/js-compilation-service/transformJs.js +9 -5
- package/src/internal/compiling/jsenvCompilerForHtml.js +534 -263
- package/src/internal/compiling/jsenvCompilerForJavaScript.js +15 -11
- package/src/internal/compiling/startCompileServer.js +83 -20
- package/src/internal/compiling/transformResultToCompilationResult.js +47 -25
- package/src/internal/executing/executePlan.js +2 -0
- package/src/internal/fetchUrl.js +3 -2
- package/src/internal/integrity/integrity_algorithms.js +26 -0
- package/src/internal/integrity/integrity_parsing.js +50 -0
- package/src/internal/integrity/integrity_update.js +23 -0
- package/src/internal/integrity/integrity_validation.js +49 -0
- package/src/internal/jsenvCoreDirectoryUrl.js +2 -0
- package/src/internal/jsenv_remote_directory.js +156 -0
- package/src/internal/origin_directory_converter.js +62 -0
- package/src/internal/response_validation.js +11 -24
- package/src/internal/sourceMappingURLUtils.js +10 -0
- package/src/internal/url_conversion.js +1 -0
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
resolveUrl,
|
|
3
|
+
urlToFilename,
|
|
4
|
+
urlToRelativeUrl,
|
|
5
|
+
urlIsInsideOf,
|
|
6
|
+
} from "@jsenv/filesystem"
|
|
2
7
|
import { moveImportMap, composeTwoImportMaps } from "@jsenv/importmap"
|
|
3
8
|
import { createDetailedMessage } from "@jsenv/logger"
|
|
4
9
|
|
|
10
|
+
import { jsenvDistDirectoryUrl } from "@jsenv/core/src/internal/jsenvCoreDirectoryUrl.js"
|
|
5
11
|
import {
|
|
6
12
|
BROWSER_RUNTIME_BUILD_URL,
|
|
7
13
|
EVENT_SOURCE_CLIENT_BUILD_URL,
|
|
@@ -11,6 +17,7 @@ import { fetchUrl } from "@jsenv/core/src/internal/fetchUrl.js"
|
|
|
11
17
|
import { getDefaultImportmap } from "@jsenv/core/src/internal/import-resolution/importmap_default.js"
|
|
12
18
|
|
|
13
19
|
import {
|
|
20
|
+
generateSourcemapUrl,
|
|
14
21
|
setJavaScriptSourceMappingUrl,
|
|
15
22
|
sourcemapToBase64Url,
|
|
16
23
|
} from "../sourceMappingURLUtils.js"
|
|
@@ -23,47 +30,46 @@ import {
|
|
|
23
30
|
stringifyHtmlAst,
|
|
24
31
|
getHtmlNodeAttributeByName,
|
|
25
32
|
getHtmlNodeTextNode,
|
|
26
|
-
|
|
33
|
+
getIdForInlineHtmlNode,
|
|
27
34
|
removeHtmlNodeAttribute,
|
|
28
35
|
setHtmlNodeText,
|
|
29
36
|
visitHtmlAst,
|
|
30
|
-
|
|
37
|
+
addHtmlNodeAttribute,
|
|
31
38
|
} from "./compileHtml.js"
|
|
32
|
-
import {
|
|
39
|
+
import { generateCompilationAssetUrl } from "./compile-directory/compile-asset.js"
|
|
33
40
|
|
|
34
41
|
export const compileHtml = async ({
|
|
35
42
|
// cancellationToken,
|
|
36
43
|
logger,
|
|
37
|
-
// request,
|
|
38
|
-
code,
|
|
39
44
|
url,
|
|
40
45
|
compiledUrl,
|
|
41
46
|
projectDirectoryUrl,
|
|
47
|
+
jsenvRemoteDirectory,
|
|
48
|
+
compileServerOrigin,
|
|
42
49
|
outDirectoryRelativeUrl,
|
|
43
|
-
compileId,
|
|
44
50
|
|
|
51
|
+
compileId,
|
|
45
52
|
babelPluginMap,
|
|
46
53
|
moduleOutFormat,
|
|
47
54
|
importMetaFormat,
|
|
48
55
|
topLevelAwait,
|
|
49
|
-
|
|
50
|
-
sourcemapMethod,
|
|
51
|
-
|
|
52
56
|
jsenvScriptInjection = true,
|
|
53
57
|
jsenvEventSourceClientInjection,
|
|
54
58
|
jsenvToolbarInjection,
|
|
55
59
|
onHtmlImportmapInfo,
|
|
60
|
+
|
|
61
|
+
sourcemapMethod,
|
|
62
|
+
code,
|
|
56
63
|
}) => {
|
|
64
|
+
const compileDirectoryUrl = `${projectDirectoryUrl}${outDirectoryRelativeUrl}${compileId}/`
|
|
57
65
|
const browserRuntimeBuildUrlRelativeToProject = urlToRelativeUrl(
|
|
58
66
|
BROWSER_RUNTIME_BUILD_URL,
|
|
59
67
|
projectDirectoryUrl,
|
|
60
68
|
)
|
|
61
|
-
|
|
62
69
|
const eventSourceClientBuildRelativeUrlForProject = urlToRelativeUrl(
|
|
63
70
|
EVENT_SOURCE_CLIENT_BUILD_URL,
|
|
64
71
|
projectDirectoryUrl,
|
|
65
72
|
)
|
|
66
|
-
|
|
67
73
|
const toolbarInjectorBuildRelativeUrlForProject = urlToRelativeUrl(
|
|
68
74
|
TOOLBAR_INJECTOR_BUILD_URL,
|
|
69
75
|
projectDirectoryUrl,
|
|
@@ -71,11 +77,6 @@ export const compileHtml = async ({
|
|
|
71
77
|
|
|
72
78
|
// ideally we should try/catch html syntax error
|
|
73
79
|
const htmlAst = parseHtmlString(code)
|
|
74
|
-
|
|
75
|
-
if (moduleOutFormat !== "esmodule") {
|
|
76
|
-
await mutateRessourceHints(htmlAst)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
80
|
manipulateHtmlAst(htmlAst, {
|
|
80
81
|
scriptInjections: [
|
|
81
82
|
...(jsenvScriptInjection
|
|
@@ -104,255 +105,559 @@ export const compileHtml = async ({
|
|
|
104
105
|
],
|
|
105
106
|
})
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
const sources = []
|
|
109
|
+
const sourcesContent = []
|
|
110
|
+
const assets = []
|
|
111
|
+
const assetsContent = []
|
|
112
|
+
|
|
113
|
+
const addHtmlSourceFile = ({ url, content }) => {
|
|
114
|
+
sources.push(url)
|
|
115
|
+
sourcesContent.push(content)
|
|
116
|
+
}
|
|
117
|
+
addHtmlSourceFile({ url, content: code })
|
|
118
|
+
|
|
109
119
|
const { scripts } = parseHtmlAstRessources(htmlAst)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
120
|
+
const htmlDependencies = collectHtmlDependenciesFromAst(htmlAst)
|
|
121
|
+
|
|
122
|
+
const htmlAssetGenerators = []
|
|
123
|
+
const htmlMutations = []
|
|
124
|
+
const addHtmlAssetGenerator = (htmlAssetGenerator) => {
|
|
125
|
+
htmlAssetGenerators.push(htmlAssetGenerator)
|
|
126
|
+
}
|
|
127
|
+
const addHtmlMutation = (htmlMutation) => {
|
|
128
|
+
htmlMutations.push(htmlMutation)
|
|
129
|
+
}
|
|
130
|
+
const addHtmlDependency = ({ htmlNode, specifier }) => {
|
|
131
|
+
htmlDependencies.push({
|
|
132
|
+
htmlNode,
|
|
133
|
+
specifier,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
if (moduleOutFormat !== "esmodule") {
|
|
137
|
+
const ressourceHints = collectRessourceHints(htmlAst)
|
|
138
|
+
await visitRessourceHints({
|
|
139
|
+
ressourceHints,
|
|
140
|
+
addHtmlMutation,
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
await visitImportmapScript({
|
|
144
|
+
htmlAst,
|
|
145
|
+
logger,
|
|
146
|
+
url,
|
|
147
|
+
compiledUrl,
|
|
148
|
+
projectDirectoryUrl,
|
|
149
|
+
compileDirectoryUrl,
|
|
150
|
+
moduleOutFormat,
|
|
151
|
+
scripts,
|
|
152
|
+
addHtmlMutation,
|
|
153
|
+
addHtmlSourceFile,
|
|
154
|
+
onHtmlImportmapInfo,
|
|
155
|
+
})
|
|
156
|
+
await visitScripts({
|
|
157
|
+
logger,
|
|
158
|
+
projectDirectoryUrl,
|
|
159
|
+
jsenvRemoteDirectory,
|
|
160
|
+
compileServerOrigin,
|
|
161
|
+
url,
|
|
162
|
+
compiledUrl,
|
|
163
|
+
|
|
164
|
+
babelPluginMap,
|
|
165
|
+
moduleOutFormat,
|
|
166
|
+
importMetaFormat,
|
|
167
|
+
topLevelAwait,
|
|
168
|
+
sourcemapMethod,
|
|
169
|
+
|
|
170
|
+
scripts,
|
|
171
|
+
addHtmlSourceFile,
|
|
172
|
+
addHtmlAssetGenerator,
|
|
173
|
+
addHtmlMutation,
|
|
174
|
+
addHtmlDependency,
|
|
175
|
+
})
|
|
176
|
+
await Promise.all(
|
|
177
|
+
htmlAssetGenerators.map(async (htmlAssetGenerator) => {
|
|
178
|
+
const assetInfos = await htmlAssetGenerator()
|
|
179
|
+
assetInfos.forEach((assetInfo) => {
|
|
180
|
+
assets.push(assetInfo.url)
|
|
181
|
+
assetsContent.push(assetInfo.content)
|
|
182
|
+
})
|
|
183
|
+
}),
|
|
184
|
+
)
|
|
185
|
+
htmlAssetGenerators.length = 0
|
|
186
|
+
htmlMutations.forEach((htmlMutation) => {
|
|
187
|
+
htmlMutation()
|
|
188
|
+
})
|
|
189
|
+
htmlMutations.length = 0
|
|
190
|
+
const htmlAfterTransformation = stringifyHtmlAst(htmlAst)
|
|
191
|
+
return {
|
|
192
|
+
contentType: "text/html",
|
|
193
|
+
compiledSource: htmlAfterTransformation,
|
|
194
|
+
sources,
|
|
195
|
+
sourcesContent,
|
|
196
|
+
assets,
|
|
197
|
+
assetsContent,
|
|
198
|
+
dependencies: htmlDependencies.map(({ specifier }) => {
|
|
199
|
+
return specifier
|
|
200
|
+
}),
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// transform <link type="modulepreload"> into <link type="preload">
|
|
205
|
+
// also remove integrity attributes because we don't know in advance
|
|
206
|
+
// the result of the file compilation
|
|
207
|
+
const visitRessourceHints = async ({ ressourceHints, addHtmlMutation }) => {
|
|
208
|
+
await Promise.all(
|
|
209
|
+
ressourceHints.map(async (ressourceHint) => {
|
|
210
|
+
const hrefAttribute = getHtmlNodeAttributeByName(ressourceHint, "href")
|
|
211
|
+
const href = hrefAttribute ? hrefAttribute.value : ""
|
|
212
|
+
if (!href) {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
const integrityAttribute = getHtmlNodeAttributeByName(
|
|
216
|
+
ressourceHint,
|
|
217
|
+
"integrity",
|
|
218
|
+
)
|
|
219
|
+
if (integrityAttribute) {
|
|
220
|
+
addHtmlMutation(() => {
|
|
221
|
+
removeHtmlNodeAttribute(ressourceHint, integrityAttribute)
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
const relAttribute = getHtmlNodeAttributeByName(ressourceHint, "rel")
|
|
225
|
+
const asAttribute = getHtmlNodeAttributeByName(ressourceHint, "as")
|
|
226
|
+
// - "modulepreload" -> "preload" because it's now regular js script
|
|
227
|
+
if (ressourceHint.rel === "modulepreload") {
|
|
228
|
+
addHtmlMutation(() => {
|
|
229
|
+
relAttribute.value = "preload"
|
|
230
|
+
if (asAttribute) {
|
|
231
|
+
asAttribute.value = "script"
|
|
232
|
+
} else {
|
|
233
|
+
addHtmlNodeAttribute(ressourceHint, { name: "as", value: "script" })
|
|
169
234
|
}
|
|
170
|
-
}
|
|
235
|
+
})
|
|
236
|
+
return
|
|
171
237
|
}
|
|
172
|
-
|
|
238
|
+
// if (asAttribute && asAttribute.value === "script") {
|
|
239
|
+
// addHtmlMutation(() => {
|
|
240
|
+
// replaceHtmlNode(htmlNode, `<link as="script" />`)
|
|
241
|
+
// })
|
|
242
|
+
// return
|
|
243
|
+
// }
|
|
244
|
+
}),
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const visitImportmapScript = async ({
|
|
249
|
+
htmlAst,
|
|
250
|
+
logger,
|
|
251
|
+
url,
|
|
252
|
+
compiledUrl,
|
|
253
|
+
projectDirectoryUrl,
|
|
254
|
+
compileDirectoryUrl,
|
|
255
|
+
moduleOutFormat,
|
|
256
|
+
scripts,
|
|
257
|
+
addHtmlMutation,
|
|
258
|
+
addHtmlSourceFile,
|
|
259
|
+
onHtmlImportmapInfo,
|
|
260
|
+
}) => {
|
|
261
|
+
const importmapScripts = scripts.filter((script) => {
|
|
262
|
+
const typeAttribute = getHtmlNodeAttributeByName(script, "type")
|
|
263
|
+
const type = typeAttribute ? typeAttribute.value : "application/javascript"
|
|
264
|
+
return type === "importmap"
|
|
173
265
|
})
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
replaceHtmlNode(
|
|
178
|
-
importmapInfo.script,
|
|
179
|
-
`<script type="${
|
|
180
|
-
moduleOutFormat === "systemjs" ? "systemjs-importmap" : "importmap"
|
|
181
|
-
}">${importmapAsText}</script>`,
|
|
182
|
-
{
|
|
183
|
-
attributesToIgnore: ["src"],
|
|
184
|
-
},
|
|
185
|
-
)
|
|
186
|
-
importmapInfo.inlinedFrom = importmapInfo.url
|
|
187
|
-
importmapInfo.text = importmapAsText
|
|
188
|
-
} else {
|
|
266
|
+
// in case there is no importmap, force the presence
|
|
267
|
+
// so that '@jsenv/core/' are still remapped
|
|
268
|
+
if (importmapScripts.length === 0) {
|
|
189
269
|
const defaultImportMap = getDefaultImportmap(compiledUrl, {
|
|
190
270
|
projectDirectoryUrl,
|
|
191
|
-
compileDirectoryUrl
|
|
192
|
-
})
|
|
193
|
-
const importmapAsText = JSON.stringify(defaultImportMap, null, " ")
|
|
194
|
-
manipulateHtmlAst(htmlAst, {
|
|
195
|
-
scriptInjections: [
|
|
196
|
-
{
|
|
197
|
-
type:
|
|
198
|
-
moduleOutFormat === "systemjs" ? "systemjs-importmap" : "importmap",
|
|
199
|
-
// in case there is no importmap, force the presence
|
|
200
|
-
// so that '@jsenv/core/' are still remapped
|
|
201
|
-
text: importmapAsText,
|
|
202
|
-
},
|
|
203
|
-
],
|
|
271
|
+
compileDirectoryUrl,
|
|
204
272
|
})
|
|
205
|
-
|
|
273
|
+
const defaultImportMapAsText = JSON.stringify(defaultImportMap, null, " ")
|
|
274
|
+
onHtmlImportmapInfo({
|
|
206
275
|
url: compiledUrl,
|
|
207
|
-
text:
|
|
276
|
+
text: defaultImportMapAsText,
|
|
277
|
+
})
|
|
278
|
+
addHtmlMutation(() => {
|
|
279
|
+
manipulateHtmlAst(htmlAst, {
|
|
280
|
+
scriptInjections: [
|
|
281
|
+
{
|
|
282
|
+
type:
|
|
283
|
+
moduleOutFormat === "systemjs"
|
|
284
|
+
? "systemjs-importmap"
|
|
285
|
+
: "importmap",
|
|
286
|
+
text: defaultImportMapAsText,
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
if (importmapScripts.length > 1) {
|
|
294
|
+
logger.error("HTML file must contain max 1 importmap")
|
|
295
|
+
}
|
|
296
|
+
const firstImportmapScript = importmapScripts[0]
|
|
297
|
+
const srcAttribute = getHtmlNodeAttributeByName(firstImportmapScript, "src")
|
|
298
|
+
const src = srcAttribute ? srcAttribute.value : ""
|
|
299
|
+
if (src) {
|
|
300
|
+
const importmapUrl = resolveUrl(src, url)
|
|
301
|
+
const importMapResponse = await fetchUrl(importmapUrl)
|
|
302
|
+
let importmap
|
|
303
|
+
if (importMapResponse.status === 200) {
|
|
304
|
+
const importmapAsText = await importMapResponse.text()
|
|
305
|
+
addHtmlSourceFile({
|
|
306
|
+
url: importmapUrl,
|
|
307
|
+
content: importmapAsText,
|
|
308
|
+
})
|
|
309
|
+
let htmlImportmap = JSON.parse(importmapAsText)
|
|
310
|
+
importmap = moveImportMap(htmlImportmap, importmapUrl, url)
|
|
311
|
+
} else {
|
|
312
|
+
logger.warn(
|
|
313
|
+
createDetailedMessage(
|
|
314
|
+
importMapResponse.status === 404
|
|
315
|
+
? `importmap script file cannot be found.`
|
|
316
|
+
: `importmap script file unexpected response status (${importMapResponse.status}).`,
|
|
317
|
+
{
|
|
318
|
+
"importmap url": importmapUrl,
|
|
319
|
+
"html url": url,
|
|
320
|
+
},
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
importmap = {}
|
|
208
324
|
}
|
|
325
|
+
const importmapAsText = JSON.stringify(importmap, null, " ")
|
|
326
|
+
onHtmlImportmapInfo({
|
|
327
|
+
url: importmapUrl,
|
|
328
|
+
text: importmapAsText,
|
|
329
|
+
})
|
|
330
|
+
addHtmlMutation(() => {
|
|
331
|
+
removeHtmlNodeAttribute(firstImportmapScript, srcAttribute)
|
|
332
|
+
setHtmlNodeText(firstImportmapScript, importmapAsText)
|
|
333
|
+
if (moduleOutFormat === "systemjs") {
|
|
334
|
+
const typeAttribute = getHtmlNodeAttributeByName(
|
|
335
|
+
firstImportmapScript,
|
|
336
|
+
"type",
|
|
337
|
+
)
|
|
338
|
+
typeAttribute.value = "systemjs-importmap"
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
return
|
|
209
342
|
}
|
|
343
|
+
|
|
344
|
+
const jsenvImportmap = getDefaultImportmap(compiledUrl, {
|
|
345
|
+
projectDirectoryUrl,
|
|
346
|
+
compileDirectoryUrl,
|
|
347
|
+
})
|
|
348
|
+
const htmlImportmap = JSON.parse(
|
|
349
|
+
getHtmlNodeTextNode(firstImportmapScript).value,
|
|
350
|
+
)
|
|
351
|
+
const importmap = composeTwoImportMaps(jsenvImportmap, htmlImportmap)
|
|
352
|
+
const importmapAsText = JSON.stringify(importmap, null, " ")
|
|
210
353
|
onHtmlImportmapInfo({
|
|
211
|
-
|
|
212
|
-
|
|
354
|
+
url: compiledUrl,
|
|
355
|
+
text: importmapAsText,
|
|
213
356
|
})
|
|
357
|
+
addHtmlMutation(() => {
|
|
358
|
+
removeHtmlNodeAttribute(firstImportmapScript, srcAttribute)
|
|
359
|
+
setHtmlNodeText(firstImportmapScript, importmapAsText)
|
|
360
|
+
if (moduleOutFormat === "systemjs") {
|
|
361
|
+
const typeAttribute = getHtmlNodeAttributeByName(
|
|
362
|
+
firstImportmapScript,
|
|
363
|
+
"type",
|
|
364
|
+
)
|
|
365
|
+
typeAttribute.value = "systemjs-importmap"
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
return
|
|
369
|
+
}
|
|
214
370
|
|
|
215
|
-
|
|
216
|
-
|
|
371
|
+
const visitScripts = async ({
|
|
372
|
+
logger,
|
|
373
|
+
projectDirectoryUrl,
|
|
374
|
+
compileServerOrigin,
|
|
375
|
+
jsenvRemoteDirectory,
|
|
376
|
+
url,
|
|
377
|
+
compiledUrl,
|
|
378
|
+
|
|
379
|
+
babelPluginMap,
|
|
380
|
+
moduleOutFormat,
|
|
381
|
+
importMetaFormat,
|
|
382
|
+
topLevelAwait,
|
|
383
|
+
sourcemapMethod,
|
|
384
|
+
|
|
385
|
+
scripts,
|
|
386
|
+
addHtmlSourceFile,
|
|
387
|
+
addHtmlAssetGenerator,
|
|
388
|
+
addHtmlMutation,
|
|
389
|
+
addHtmlDependency,
|
|
390
|
+
}) => {
|
|
217
391
|
scripts.forEach((script) => {
|
|
218
392
|
const typeAttribute = getHtmlNodeAttributeByName(script, "type")
|
|
393
|
+
const type = typeAttribute ? typeAttribute.value : "application/javascript"
|
|
219
394
|
const srcAttribute = getHtmlNodeAttributeByName(script, "src")
|
|
220
395
|
const src = srcAttribute ? srcAttribute.value : ""
|
|
221
|
-
|
|
222
|
-
if (typeAttribute && typeAttribute.value === "module" && src) {
|
|
223
|
-
if (moduleOutFormat === "systemjs") {
|
|
224
|
-
removeHtmlNodeAttribute(script, typeAttribute)
|
|
225
|
-
}
|
|
226
|
-
removeHtmlNodeAttribute(script, srcAttribute)
|
|
227
|
-
const jsenvMethod =
|
|
228
|
-
moduleOutFormat === "systemjs"
|
|
229
|
-
? "executeFileUsingSystemJs"
|
|
230
|
-
: "executeFileUsingDynamicImport"
|
|
231
|
-
setHtmlNodeText(
|
|
232
|
-
script,
|
|
233
|
-
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(src)})`,
|
|
234
|
-
)
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// inline module script
|
|
396
|
+
const integrityAttribute = getHtmlNodeAttributeByName(script, "integrity")
|
|
239
397
|
const textNode = getHtmlNodeTextNode(script)
|
|
240
|
-
if (
|
|
241
|
-
if (
|
|
242
|
-
|
|
398
|
+
if (type === "module") {
|
|
399
|
+
if (src) {
|
|
400
|
+
addHtmlMutation(() => {
|
|
401
|
+
if (moduleOutFormat === "systemjs") {
|
|
402
|
+
removeHtmlNodeAttribute(script, typeAttribute)
|
|
403
|
+
}
|
|
404
|
+
if (integrityAttribute) {
|
|
405
|
+
removeHtmlNodeAttribute(script, integrityAttribute)
|
|
406
|
+
}
|
|
407
|
+
removeHtmlNodeAttribute(script, srcAttribute)
|
|
408
|
+
const jsenvMethod =
|
|
409
|
+
moduleOutFormat === "systemjs"
|
|
410
|
+
? "executeFileUsingSystemJs"
|
|
411
|
+
: "executeFileUsingDynamicImport"
|
|
412
|
+
let specifier
|
|
413
|
+
if (
|
|
414
|
+
jsenvRemoteDirectory.isRemoteUrl(src) &&
|
|
415
|
+
!jsenvRemoteDirectory.isPreservedUrl(src)
|
|
416
|
+
) {
|
|
417
|
+
const fileUrl = jsenvRemoteDirectory.fileUrlFromRemoteUrl(src)
|
|
418
|
+
const fileUrlRelativeToHtml = urlToRelativeUrl(fileUrl, url)
|
|
419
|
+
specifier = `./${fileUrlRelativeToHtml}`
|
|
420
|
+
} else {
|
|
421
|
+
specifier = src
|
|
422
|
+
}
|
|
423
|
+
setHtmlNodeText(
|
|
424
|
+
script,
|
|
425
|
+
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
426
|
+
)
|
|
427
|
+
})
|
|
428
|
+
return
|
|
243
429
|
}
|
|
244
|
-
|
|
245
|
-
const
|
|
430
|
+
|
|
431
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
432
|
+
const inlineScriptName = `${scriptId}.js`
|
|
433
|
+
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
434
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
246
435
|
compiledUrl,
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
const specifier = `./${urlToRelativeUrl(scriptAssetUrl, compiledUrl)}`
|
|
250
|
-
inlineScriptsContentMap[specifier] = textNode.value
|
|
251
|
-
const jsenvMethod =
|
|
252
|
-
moduleOutFormat === "systemjs"
|
|
253
|
-
? "executeFileUsingSystemJs"
|
|
254
|
-
: "executeFileUsingDynamicImport"
|
|
255
|
-
setHtmlNodeText(
|
|
256
|
-
script,
|
|
257
|
-
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
436
|
+
inlineScriptName,
|
|
258
437
|
)
|
|
259
|
-
|
|
438
|
+
addHtmlAssetGenerator(async () => {
|
|
439
|
+
return transformHtmlScript({
|
|
440
|
+
projectDirectoryUrl,
|
|
441
|
+
jsenvRemoteDirectory,
|
|
442
|
+
url: scriptOriginalUrl,
|
|
443
|
+
compiledUrl: scriptCompiledUrl,
|
|
444
|
+
|
|
445
|
+
type: "module",
|
|
446
|
+
babelPluginMap,
|
|
447
|
+
moduleOutFormat,
|
|
448
|
+
importMetaFormat,
|
|
449
|
+
topLevelAwait,
|
|
450
|
+
|
|
451
|
+
sourcemapMethod,
|
|
452
|
+
code: textNode.value,
|
|
453
|
+
})
|
|
454
|
+
})
|
|
455
|
+
const specifier = `./${urlToRelativeUrl(scriptCompiledUrl, compiledUrl)}`
|
|
456
|
+
addHtmlMutation(() => {
|
|
457
|
+
if (moduleOutFormat === "systemjs") {
|
|
458
|
+
removeHtmlNodeAttribute(script, typeAttribute)
|
|
459
|
+
}
|
|
460
|
+
removeHtmlNodeAttribute(script, srcAttribute)
|
|
461
|
+
const jsenvMethod =
|
|
462
|
+
moduleOutFormat === "systemjs"
|
|
463
|
+
? "executeFileUsingSystemJs"
|
|
464
|
+
: "executeFileUsingDynamicImport"
|
|
465
|
+
setHtmlNodeText(
|
|
466
|
+
script,
|
|
467
|
+
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
468
|
+
)
|
|
469
|
+
})
|
|
470
|
+
addHtmlDependency({
|
|
260
471
|
htmlNode: script,
|
|
261
472
|
specifier,
|
|
262
473
|
})
|
|
263
474
|
return
|
|
264
475
|
}
|
|
265
|
-
|
|
266
|
-
|
|
476
|
+
if (type === "application/javascript" || type === "text/javascript") {
|
|
477
|
+
if (src) {
|
|
478
|
+
const htmlServerUrl = url.replace(
|
|
479
|
+
projectDirectoryUrl,
|
|
480
|
+
`${compileServerOrigin}/`,
|
|
481
|
+
)
|
|
482
|
+
const scriptOriginalServerUrl = resolveUrl(src, htmlServerUrl)
|
|
483
|
+
const scriptOriginalUrl = scriptOriginalServerUrl.replace(
|
|
484
|
+
`${compileServerOrigin}/`,
|
|
485
|
+
projectDirectoryUrl,
|
|
486
|
+
)
|
|
487
|
+
const fileIsInsideJsenvDistDirectory = urlIsInsideOf(
|
|
488
|
+
scriptOriginalUrl,
|
|
489
|
+
jsenvDistDirectoryUrl,
|
|
490
|
+
)
|
|
491
|
+
if (fileIsInsideJsenvDistDirectory) {
|
|
492
|
+
return
|
|
493
|
+
}
|
|
267
494
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
495
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
496
|
+
compiledUrl,
|
|
497
|
+
urlToFilename(scriptOriginalUrl),
|
|
498
|
+
)
|
|
499
|
+
addHtmlAssetGenerator(async () => {
|
|
500
|
+
// we fetch scriptOriginalUrl on purpose because we do
|
|
501
|
+
// the transformation here and not in compile server
|
|
502
|
+
// (because compile server would think it's a module script
|
|
503
|
+
// and add things like systemjs)
|
|
504
|
+
const scriptResponse = await fetchUrl(scriptOriginalUrl)
|
|
505
|
+
if (scriptResponse.status !== 200) {
|
|
506
|
+
logger.warn(
|
|
507
|
+
createDetailedMessage(
|
|
508
|
+
scriptResponse.status === 404
|
|
509
|
+
? `script file cannot be found.`
|
|
510
|
+
: `script file unexpected response status (${scriptResponse.status}).`,
|
|
511
|
+
{
|
|
512
|
+
"script url": script.url,
|
|
513
|
+
"html url": url,
|
|
514
|
+
},
|
|
515
|
+
),
|
|
516
|
+
)
|
|
517
|
+
return []
|
|
518
|
+
}
|
|
519
|
+
const scriptAsText = await scriptResponse.text()
|
|
520
|
+
addHtmlSourceFile({
|
|
521
|
+
url: scriptOriginalUrl,
|
|
522
|
+
content: scriptAsText,
|
|
523
|
+
})
|
|
524
|
+
return transformHtmlScript({
|
|
525
|
+
projectDirectoryUrl,
|
|
526
|
+
jsenvRemoteDirectory,
|
|
527
|
+
url: scriptOriginalUrl,
|
|
528
|
+
compiledUrl: scriptCompiledUrl,
|
|
529
|
+
|
|
530
|
+
type: "classic",
|
|
531
|
+
babelPluginMap,
|
|
532
|
+
moduleOutFormat,
|
|
533
|
+
importMetaFormat,
|
|
534
|
+
topLevelAwait,
|
|
535
|
+
|
|
536
|
+
sourcemapMethod,
|
|
537
|
+
code: scriptAsText,
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
addHtmlMutation(() => {
|
|
541
|
+
if (integrityAttribute) {
|
|
542
|
+
removeHtmlNodeAttribute(script, integrityAttribute)
|
|
543
|
+
}
|
|
544
|
+
srcAttribute.value = `./${urlToRelativeUrl(
|
|
545
|
+
scriptCompiledUrl,
|
|
546
|
+
compiledUrl,
|
|
547
|
+
)}`
|
|
548
|
+
})
|
|
549
|
+
return
|
|
550
|
+
}
|
|
551
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
552
|
+
const inlineScriptName = `${scriptId}.js`
|
|
553
|
+
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
554
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
555
|
+
compiledUrl,
|
|
556
|
+
inlineScriptName,
|
|
557
|
+
)
|
|
558
|
+
addHtmlAssetGenerator(async () => {
|
|
559
|
+
const htmlAssets = await transformHtmlScript({
|
|
284
560
|
projectDirectoryUrl,
|
|
561
|
+
jsenvRemoteDirectory,
|
|
562
|
+
url: scriptOriginalUrl,
|
|
563
|
+
compiledUrl: scriptCompiledUrl,
|
|
285
564
|
|
|
565
|
+
type: "classic",
|
|
286
566
|
babelPluginMap,
|
|
287
567
|
moduleOutFormat,
|
|
288
568
|
importMetaFormat,
|
|
289
569
|
topLevelAwait,
|
|
570
|
+
|
|
571
|
+
code: textNode.value,
|
|
572
|
+
sourcemapMethod,
|
|
290
573
|
})
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const code = scriptBeforeCompilation
|
|
301
|
-
assets = [...assets, scriptAssetUrl]
|
|
302
|
-
assetsContent = [...assetsContent, code]
|
|
303
|
-
return
|
|
304
|
-
}
|
|
305
|
-
throw e
|
|
306
|
-
}
|
|
307
|
-
const sourcemapFileUrl = resolveUrl(
|
|
308
|
-
`${scriptBasename}.map`,
|
|
309
|
-
scriptCompiledFileUrl,
|
|
310
|
-
)
|
|
574
|
+
addHtmlMutation(() => {
|
|
575
|
+
setHtmlNodeText(script, htmlAssets[0].content)
|
|
576
|
+
})
|
|
577
|
+
return htmlAssets
|
|
578
|
+
})
|
|
579
|
+
return
|
|
580
|
+
}
|
|
581
|
+
})
|
|
582
|
+
}
|
|
311
583
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
584
|
+
const transformHtmlScript = async ({
|
|
585
|
+
projectDirectoryUrl,
|
|
586
|
+
jsenvRemoteDirectory,
|
|
587
|
+
url,
|
|
588
|
+
compiledUrl,
|
|
317
589
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
code,
|
|
324
|
-
sourcemapFileRelativePathForModule,
|
|
325
|
-
)
|
|
326
|
-
assets = [...assets, scriptAssetUrl, sourcemapFileUrl]
|
|
327
|
-
assetsContent = [
|
|
328
|
-
...assetsContent,
|
|
329
|
-
code,
|
|
330
|
-
JSON.stringify(map, null, " "),
|
|
331
|
-
]
|
|
332
|
-
}
|
|
333
|
-
}),
|
|
334
|
-
)
|
|
335
|
-
sources.push(url)
|
|
336
|
-
sourcesContent.push(code)
|
|
590
|
+
type,
|
|
591
|
+
babelPluginMap,
|
|
592
|
+
moduleOutFormat,
|
|
593
|
+
importMetaFormat,
|
|
594
|
+
topLevelAwait,
|
|
337
595
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
596
|
+
code,
|
|
597
|
+
sourcemapMethod,
|
|
598
|
+
}) => {
|
|
599
|
+
let transformResult
|
|
600
|
+
try {
|
|
601
|
+
transformResult = await transformJs({
|
|
602
|
+
projectDirectoryUrl,
|
|
603
|
+
jsenvRemoteDirectory,
|
|
604
|
+
url,
|
|
605
|
+
compiledUrl,
|
|
606
|
+
|
|
607
|
+
babelPluginMap,
|
|
608
|
+
moduleOutFormat: type === "module" ? moduleOutFormat : "global",
|
|
609
|
+
importMetaFormat,
|
|
610
|
+
topLevelAwait: type === "module" ? topLevelAwait : false,
|
|
611
|
+
babelHelpersInjectionAsImport: type === "module" ? undefined : false,
|
|
612
|
+
|
|
613
|
+
code,
|
|
614
|
+
})
|
|
615
|
+
} catch (e) {
|
|
616
|
+
// If there is a syntax error in inline script
|
|
617
|
+
// we put the raw script without transformation.
|
|
618
|
+
// when systemjs will try to instantiate to script it
|
|
619
|
+
// will re-throw this syntax error.
|
|
620
|
+
// Thanks to this we see the syntax error in the
|
|
621
|
+
// document and livereloading still works
|
|
622
|
+
// because we gracefully handle this error
|
|
623
|
+
if (e.code === "PARSE_ERROR") {
|
|
624
|
+
return [{ url, content: code }]
|
|
625
|
+
}
|
|
626
|
+
throw e
|
|
348
627
|
}
|
|
628
|
+
|
|
629
|
+
code = transformResult.code
|
|
630
|
+
let map = transformResult.map
|
|
631
|
+
const sourcemapUrl = generateSourcemapUrl(compiledUrl)
|
|
632
|
+
if (sourcemapMethod === "inline") {
|
|
633
|
+
code = setJavaScriptSourceMappingUrl(code, sourcemapToBase64Url(map))
|
|
634
|
+
return [
|
|
635
|
+
{
|
|
636
|
+
url: compiledUrl,
|
|
637
|
+
content: code,
|
|
638
|
+
},
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
const sourcemapSpecifier = urlToRelativeUrl(sourcemapUrl, compiledUrl)
|
|
642
|
+
code = setJavaScriptSourceMappingUrl(code, sourcemapSpecifier)
|
|
643
|
+
return [
|
|
644
|
+
{
|
|
645
|
+
url: compiledUrl,
|
|
646
|
+
content: code,
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
url: sourcemapUrl,
|
|
650
|
+
content: JSON.stringify(map, null, " "),
|
|
651
|
+
},
|
|
652
|
+
]
|
|
349
653
|
}
|
|
350
654
|
|
|
351
|
-
|
|
352
|
-
const mutateRessourceHints = async (htmlAst) => {
|
|
655
|
+
const collectRessourceHints = (htmlAst) => {
|
|
353
656
|
const ressourceHints = []
|
|
354
657
|
visitHtmlAst(htmlAst, (htmlNode) => {
|
|
355
|
-
if (htmlNode.nodeName !== "link")
|
|
658
|
+
if (htmlNode.nodeName !== "link") {
|
|
659
|
+
return
|
|
660
|
+
}
|
|
356
661
|
const relAttribute = getHtmlNodeAttributeByName(htmlNode, "rel")
|
|
357
662
|
const rel = relAttribute ? relAttribute.value : ""
|
|
358
663
|
const isRessourceHint = [
|
|
@@ -362,44 +667,10 @@ const mutateRessourceHints = async (htmlAst) => {
|
|
|
362
667
|
"preload",
|
|
363
668
|
"modulepreload",
|
|
364
669
|
].includes(rel)
|
|
365
|
-
if (!isRessourceHint)
|
|
366
|
-
|
|
367
|
-
|
|
670
|
+
if (!isRessourceHint) {
|
|
671
|
+
return
|
|
672
|
+
}
|
|
673
|
+
ressourceHints.push(htmlNode)
|
|
368
674
|
})
|
|
369
|
-
|
|
370
|
-
const mutations = []
|
|
371
|
-
await Promise.all(
|
|
372
|
-
ressourceHints.map(async (ressourceHint) => {
|
|
373
|
-
const hrefAttribute = getHtmlNodeAttributeByName(
|
|
374
|
-
ressourceHint.htmlNode,
|
|
375
|
-
"href",
|
|
376
|
-
)
|
|
377
|
-
const href = hrefAttribute ? hrefAttribute.value : ""
|
|
378
|
-
if (!href) return
|
|
379
|
-
|
|
380
|
-
// - "modulepreload" -> "preload" because it's now regular js script
|
|
381
|
-
const asAttribute = getHtmlNodeAttributeByName(
|
|
382
|
-
ressourceHint.htmlNode,
|
|
383
|
-
"as",
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
if (ressourceHint.rel === "modulepreload") {
|
|
387
|
-
mutations.push(() => {
|
|
388
|
-
replaceHtmlNode(
|
|
389
|
-
ressourceHint.htmlNode,
|
|
390
|
-
`<link rel="preload" as="script" />`,
|
|
391
|
-
)
|
|
392
|
-
})
|
|
393
|
-
return
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (asAttribute && asAttribute.value === "script") {
|
|
397
|
-
mutations.push(() => {
|
|
398
|
-
replaceHtmlNode(ressourceHint.htmlNode, `<link as="script" />`)
|
|
399
|
-
})
|
|
400
|
-
return
|
|
401
|
-
}
|
|
402
|
-
}),
|
|
403
|
-
)
|
|
404
|
-
mutations.forEach((mutation) => mutation())
|
|
675
|
+
return ressourceHints
|
|
405
676
|
}
|