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