@jsenv/core 36.3.1 → 37.0.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 (64) hide show
  1. package/dist/js/autoreload.js +6 -5
  2. package/dist/js/import_meta_hot.js +4 -4
  3. package/dist/js/server_events_client.js +422 -304
  4. package/dist/jsenv_core.js +3819 -3256
  5. package/package.json +16 -16
  6. package/src/build/build.js +342 -658
  7. package/src/build/build_urls_generator.js +8 -8
  8. package/src/build/build_versions_manager.js +495 -0
  9. package/src/build/version_mappings_injection.js +27 -16
  10. package/src/dev/file_service.js +80 -91
  11. package/src/dev/start_dev_server.js +5 -3
  12. package/src/kitchen/errors.js +16 -16
  13. package/src/kitchen/fetched_content_compliance.js +4 -8
  14. package/src/kitchen/kitchen.js +367 -939
  15. package/src/kitchen/prepend_content.js +13 -35
  16. package/src/kitchen/url_graph/references.js +713 -0
  17. package/src/kitchen/url_graph/sort_by_dependencies.js +2 -2
  18. package/src/kitchen/url_graph/url_content.js +96 -0
  19. package/src/kitchen/url_graph/url_graph.js +439 -0
  20. package/src/kitchen/url_graph/url_graph_report.js +6 -4
  21. package/src/kitchen/url_graph/url_graph_visitor.js +14 -12
  22. package/src/kitchen/url_graph/url_info_transformations.js +180 -184
  23. package/src/plugins/autoreload/client/autoreload.js +1 -0
  24. package/src/plugins/autoreload/client/reload.js +6 -6
  25. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +2 -2
  26. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +2 -2
  27. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +84 -78
  28. package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +52 -0
  29. package/src/plugins/cache_control/jsenv_plugin_cache_control.js +1 -1
  30. package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +2 -2
  31. package/src/plugins/global_scenarios/jsenv_plugin_global_scenarios.js +3 -3
  32. package/src/plugins/import_meta_hot/client/import_meta_hot.js +4 -4
  33. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +18 -20
  34. package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +2 -2
  35. package/src/plugins/importmap/jsenv_plugin_importmap.js +35 -37
  36. package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -17
  37. package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +70 -50
  38. package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +72 -54
  39. package/src/plugins/plugin_controller.js +92 -27
  40. package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +18 -20
  41. package/src/plugins/reference_analysis/css/jsenv_plugin_css_reference_analysis.js +4 -5
  42. package/src/plugins/reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js +18 -16
  43. package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +13 -20
  44. package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +55 -72
  45. package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +33 -42
  46. package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +16 -7
  47. package/src/plugins/reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js +4 -3
  48. package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +16 -6
  49. package/src/plugins/resolution_node_esm/node_esm_resolver.js +30 -24
  50. package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +8 -5
  51. package/src/plugins/ribbon/jsenv_plugin_ribbon.js +3 -3
  52. package/src/plugins/server_events/client/server_events_client.js +460 -15
  53. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +13 -29
  54. package/src/plugins/version_search_param/jsenv_plugin_version_search_param.js +1 -1
  55. package/src/build/version_generator.js +0 -19
  56. package/src/kitchen/url_graph/url_graph_loader.js +0 -77
  57. package/src/kitchen/url_graph.js +0 -322
  58. package/src/plugins/autoreload/jsenv_plugin_hmr.js +0 -42
  59. package/src/plugins/resolution_node_esm/url_type_from_reference.js +0 -13
  60. package/src/plugins/server_events/client/connection_manager.js +0 -170
  61. package/src/plugins/server_events/client/event_source_connection.js +0 -83
  62. package/src/plugins/server_events/client/events_manager.js +0 -75
  63. package/src/plugins/server_events/client/web_socket_connection.js +0 -81
  64. /package/src/kitchen/{url_specifier_encoding.js → url_graph/url_specifier_encoding.js} +0 -0
@@ -5,7 +5,7 @@
5
5
  * 3. refine
6
6
  *
7
7
  * craft: prepare all the materials
8
- * - resolve, fetch and transform all source files into "rawGraph"
8
+ * - resolve, fetch and transform all source files into "rawKitchen.graph"
9
9
  * shape: this step can drastically change url content and their relationships
10
10
  * - bundling
11
11
  * - optimizations (minification)
@@ -17,14 +17,9 @@
17
17
  */
18
18
 
19
19
  import {
20
- injectQueryParams,
21
- setUrlFilename,
22
- normalizeUrl,
23
20
  asUrlWithoutSearch,
24
21
  ensurePathnameTrailingSlash,
25
22
  urlIsInsideOf,
26
- urlToBasename,
27
- urlToExtension,
28
23
  urlToRelativeUrl,
29
24
  } from "@jsenv/urls";
30
25
  import {
@@ -40,7 +35,7 @@ import {
40
35
  ANSI,
41
36
  createDetailedMessage,
42
37
  } from "@jsenv/log";
43
- import { createMagicSource, generateSourcemapFileUrl } from "@jsenv/sourcemap";
38
+ import { generateSourcemapFileUrl } from "@jsenv/sourcemap";
44
39
  import {
45
40
  parseHtmlString,
46
41
  stringifyHtmlAst,
@@ -58,25 +53,17 @@ import { jsenvPluginJsModuleFallback } from "@jsenv/plugin-transpilation";
58
53
  import { lookupPackageDirectory } from "../helpers/lookup_package_directory.js";
59
54
  import { watchSourceFiles } from "../helpers/watch_source_files.js";
60
55
  import { GRAPH_VISITOR } from "../kitchen/url_graph/url_graph_visitor.js";
61
- import { createUrlGraph } from "../kitchen/url_graph.js";
62
56
  import { createKitchen } from "../kitchen/kitchen.js";
63
- import { createUrlGraphLoader } from "../kitchen/url_graph/url_graph_loader.js";
64
57
  import { createUrlGraphSummary } from "../kitchen/url_graph/url_graph_report.js";
65
- import {
66
- isWebWorkerEntryPointReference,
67
- isWebWorkerUrlInfo,
68
- } from "../kitchen/web_workers.js";
58
+ import { isWebWorkerEntryPointReference } from "../kitchen/web_workers.js";
59
+ import { prependContent } from "../kitchen/prepend_content.js";
69
60
  import { getCorePlugins } from "../plugins/plugins.js";
70
61
  import { jsenvPluginReferenceAnalysis } from "../plugins/reference_analysis/jsenv_plugin_reference_analysis.js";
71
62
  import { jsenvPluginInlining } from "../plugins/inlining/jsenv_plugin_inlining.js";
72
63
  import { jsenvPluginLineBreakNormalization } from "./jsenv_plugin_line_break_normalization.js";
73
64
 
74
65
  import { createBuildUrlsGenerator } from "./build_urls_generator.js";
75
- import {
76
- injectVersionMappingsAsGlobal,
77
- injectVersionMappingsAsImportmap,
78
- } from "./version_mappings_injection.js";
79
- import { createVersionGenerator } from "./version_generator.js";
66
+ import { createBuildVersionsManager } from "./build_versions_manager.js";
80
67
 
81
68
  // default runtimeCompat corresponds to
82
69
  // "we can keep <script type="module"> intact":
@@ -145,6 +132,7 @@ export const build = async ({
145
132
  versioning = !runtimeCompat.node,
146
133
  versioningMethod = "search_param", // "filename", "search_param"
147
134
  versioningViaImportmap = true,
135
+ versionLength = 8,
148
136
  lineBreakNormalization = process.platform === "win32",
149
137
 
150
138
  sourceFilesConfig = {},
@@ -243,14 +231,13 @@ export const build = async ({
243
231
  }
244
232
  }
245
233
 
246
- const asFormattedBuildUrl = (generatedUrl, reference) => {
234
+ const asFormattedBuildSpecifier = (reference, generatedUrl) => {
247
235
  if (base === "./") {
248
- const urlRelativeToParent = urlToRelativeUrl(
249
- generatedUrl,
250
- reference.parentUrl === sourceDirectoryUrl
236
+ const parentUrl =
237
+ reference.ownerUrlInfo.url === sourceDirectoryUrl
251
238
  ? buildDirectoryUrl
252
- : reference.parentUrl,
253
- );
239
+ : reference.ownerUrlInfo.url;
240
+ const urlRelativeToParent = urlToRelativeUrl(generatedUrl, parentUrl);
254
241
  if (urlRelativeToParent[0] !== ".") {
255
242
  // ensure "./" on relative url (otherwise it could be a "bare specifier")
256
243
  return `./${urlRelativeToParent}`;
@@ -284,16 +271,16 @@ build "${entryPointKeys[0]}"`);
284
271
  build ${entryPointKeys.length} entry points`);
285
272
  }
286
273
  const explicitJsModuleFallback = entryPointKeys.some((key) =>
287
- entryPoints[key].includes("?js_module_fallback"),
274
+ key.includes("?js_module_fallback"),
288
275
  );
289
276
  const rawRedirections = new Map();
290
277
  const bundleRedirections = new Map();
291
278
  const bundleInternalRedirections = new Map();
292
279
  const finalRedirections = new Map();
293
- const versioningRedirections = new Map();
294
280
  const entryUrls = [];
295
- const rawGraph = createUrlGraph();
296
281
  const contextSharedDuringBuild = {
282
+ buildDirectoryUrl,
283
+ assetsDirectory,
297
284
  systemJsTranspilation: (() => {
298
285
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
299
286
  if (nodeRuntimeEnabled) return false;
@@ -315,7 +302,7 @@ build ${entryPointKeys.length} entry points`);
315
302
  (plugin) => plugin.name === "jsenv:minification",
316
303
  ),
317
304
  };
318
- const rawGraphKitchen = createKitchen({
305
+ const rawKitchen = createKitchen({
319
306
  signal,
320
307
  logLevel,
321
308
  rootDirectoryUrl: sourceDirectoryUrl,
@@ -323,26 +310,24 @@ build ${entryPointKeys.length} entry points`);
323
310
  // during first pass (craft) we keep "ignore:" when a reference is ignored
324
311
  // so that the second pass (shape) properly ignore those urls
325
312
  ignoreProtocol: "keep",
326
- urlGraph: rawGraph,
327
313
  build: true,
328
314
  runtimeCompat,
329
- ...contextSharedDuringBuild,
315
+ baseContext: contextSharedDuringBuild,
330
316
  plugins: [
331
317
  ...plugins,
332
318
  {
333
319
  appliesDuring: "build",
334
- fetchUrlContent: (urlInfo, context) => {
335
- if (context.reference.original) {
320
+ fetchUrlContent: (urlInfo) => {
321
+ if (urlInfo.firstReference.original) {
336
322
  rawRedirections.set(
337
- context.reference.original.url,
338
- context.reference.url,
323
+ urlInfo.firstReference.original.url,
324
+ urlInfo.firstReference.url,
339
325
  );
340
326
  }
341
327
  },
342
328
  },
343
329
  ...getCorePlugins({
344
330
  rootDirectoryUrl: sourceDirectoryUrl,
345
- urlGraph: rawGraph,
346
331
  runtimeCompat,
347
332
  referenceAnalysis,
348
333
  nodeEsmResolution,
@@ -371,22 +356,22 @@ build ${entryPointKeys.length} entry points`);
371
356
  assetsDirectory,
372
357
  });
373
358
  const buildDirectoryRedirections = new Map();
374
-
375
359
  const associateBuildUrlAndRawUrl = (buildUrl, rawUrl, reason) => {
376
360
  if (urlIsInsideOf(rawUrl, buildDirectoryUrl)) {
377
361
  throw new Error(`raw url must be inside rawGraph, got ${rawUrl}`);
378
362
  }
379
- logger.debug(`build url generated (${reason})
363
+ if (buildDirectoryRedirections.get(buildUrl) !== rawUrl) {
364
+ logger.debug(`build url generated (${reason})
380
365
  ${ANSI.color(rawUrl, ANSI.GREY)} ->
381
366
  ${ANSI.color(buildUrl, ANSI.MAGENTA)}
382
367
  `);
383
- buildDirectoryRedirections.set(buildUrl, rawUrl);
368
+ buildDirectoryRedirections.set(buildUrl, rawUrl);
369
+ }
384
370
  };
385
- const buildUrls = new Map();
371
+ const buildSpecifierMap = new Map();
386
372
  const bundleUrlInfos = {};
387
373
  const bundlers = {};
388
- const finalGraph = createUrlGraph();
389
- let finalGraphKitchen;
374
+ let finalKitchen;
390
375
  let finalEntryUrls = [];
391
376
 
392
377
  craft: {
@@ -395,24 +380,22 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
395
380
  if (outDirectoryUrl) {
396
381
  await ensureEmptyDirectory(new URL(`build/`, outDirectoryUrl));
397
382
  }
398
- const rawUrlGraphLoader = createUrlGraphLoader(
399
- rawGraphKitchen.kitchenContext,
400
- );
401
- Object.keys(entryPoints).forEach((key) => {
402
- const [entryReference, entryUrlInfo] =
403
- rawGraphKitchen.kitchenContext.prepareEntryPoint({
383
+ const rawRootUrlInfo = rawKitchen.graph.rootUrlInfo;
384
+ await rawRootUrlInfo.dependencies.startCollecting(() => {
385
+ Object.keys(entryPoints).forEach((key) => {
386
+ const entryReference = rawRootUrlInfo.dependencies.found({
404
387
  trace: { message: `"${key}" in entryPoints parameter` },
405
- parentUrl: sourceDirectoryUrl,
388
+ isEntryPoint: true,
406
389
  type: "entry_point",
407
390
  specifier: key,
391
+ filename: entryPoints[key],
408
392
  });
409
- entryUrls.push(entryUrlInfo.url);
410
- entryUrlInfo.filename = entryPoints[key];
411
- entryUrlInfo.isEntryPoint = true;
412
- rawUrlGraphLoader.load(entryUrlInfo, { reference: entryReference });
393
+ entryUrls.push(entryReference.url);
394
+ });
395
+ });
396
+ await rawRootUrlInfo.cookDependencies({
397
+ operation: buildOperation,
413
398
  });
414
- await rawUrlGraphLoader.getAllLoadDonePromise(buildOperation);
415
- await rawGraphKitchen.injectForwardedSideEffectFiles();
416
399
  } catch (e) {
417
400
  generateSourceGraph.fail();
418
401
  throw e;
@@ -420,8 +403,11 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
420
403
  generateSourceGraph.done();
421
404
  }
422
405
 
406
+ let buildVersionsManager;
407
+
423
408
  shape: {
424
- finalGraphKitchen = createKitchen({
409
+ finalKitchen = createKitchen({
410
+ name: "shape",
425
411
  logLevel,
426
412
  rootDirectoryUrl: buildDirectoryUrl,
427
413
  // here most plugins are not there
@@ -431,11 +417,11 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
431
417
  // consequently only a subset or urls are supported
432
418
  supportedProtocols: ["file:", "data:", "virtual:", "ignore:"],
433
419
  ignore,
434
- ignoreProtocol: versioning ? "keep" : "remove",
435
- urlGraph: finalGraph,
420
+ ignoreProtocol: "remove",
436
421
  build: true,
422
+ shape: true,
437
423
  runtimeCompat,
438
- ...contextSharedDuringBuild,
424
+ baseContext: contextSharedDuringBuild,
439
425
  plugins: [
440
426
  jsenvPluginReferenceAnalysis({
441
427
  ...referenceAnalysis,
@@ -452,11 +438,11 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
452
438
  resolveReference: (reference) => {
453
439
  const getUrl = () => {
454
440
  if (reference.type === "filesystem") {
455
- const parentRawUrl = buildDirectoryRedirections.get(
456
- reference.parentUrl,
441
+ const ownerRawUrl = buildDirectoryRedirections.get(
442
+ reference.ownerUrlInfo.url,
457
443
  );
458
- const parentUrl = ensurePathnameTrailingSlash(parentRawUrl);
459
- return new URL(reference.specifier, parentUrl).href;
444
+ const ownerUrl = ensurePathnameTrailingSlash(ownerRawUrl);
445
+ return new URL(reference.specifier, ownerUrl).href;
460
446
  }
461
447
  if (reference.specifier[0] === "/") {
462
448
  return new URL(
@@ -466,7 +452,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
466
452
  }
467
453
  return new URL(
468
454
  reference.specifier,
469
- reference.baseUrl || reference.parentUrl,
455
+ reference.baseUrl || reference.ownerUrlInfo.url,
470
456
  ).href;
471
457
  };
472
458
  let url = getUrl();
@@ -491,18 +477,18 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
491
477
  return reference.url;
492
478
  }
493
479
  if (reference.isInline) {
494
- const parentUrlInfo = finalGraph.getUrlInfo(
495
- reference.parentUrl,
480
+ const ownerFinalUrlInfo = finalKitchen.graph.getUrlInfo(
481
+ reference.ownerUrlInfo.url,
496
482
  );
497
- const parentRawUrl = parentUrlInfo.originalUrl;
483
+ const ownerRawUrl = ownerFinalUrlInfo.originalUrl;
498
484
  const rawUrlInfo = GRAPH_VISITOR.find(
499
- rawGraph,
485
+ rawKitchen.graph,
500
486
  (rawUrlInfo) => {
501
487
  const { inlineUrlSite } = rawUrlInfo;
502
488
  // not inline
503
489
  if (!inlineUrlSite) return false;
504
490
  if (
505
- inlineUrlSite.url === parentRawUrl &&
491
+ inlineUrlSite.url === ownerRawUrl &&
506
492
  inlineUrlSite.line === reference.specifierLine &&
507
493
  inlineUrlSite.column === reference.specifierColumn
508
494
  ) {
@@ -526,7 +512,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
526
512
  }
527
513
  const buildUrl = buildUrlsGenerator.generate(reference.url, {
528
514
  urlInfo: rawUrlInfo,
529
- parentUrlInfo,
515
+ ownerUrlInfo: ownerFinalUrlInfo,
530
516
  });
531
517
  associateBuildUrlAndRawUrl(
532
518
  buildUrl,
@@ -579,7 +565,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
579
565
  return buildUrl;
580
566
  }
581
567
  // from "js_module_fallback":
582
- // - to inject "s.js"
568
+ // - to inject "s.js"
583
569
  if (reference.injected) {
584
570
  const buildUrl = buildUrlsGenerator.generate(reference.url, {
585
571
  urlInfo: {
@@ -595,17 +581,20 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
595
581
  finalRedirections.set(buildUrl, buildUrl);
596
582
  return buildUrl;
597
583
  }
598
- const rawUrlInfo = rawGraph.getUrlInfo(reference.url);
599
- const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl);
584
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(reference.url);
585
+ const ownerFinalUrlInfo = finalKitchen.graph.getUrlInfo(
586
+ reference.ownerUrlInfo.url,
587
+ );
600
588
  // files from root directory but not given to rollup nor postcss
601
589
  if (rawUrlInfo) {
602
590
  const referencedUrlObject = new URL(reference.url);
603
591
  referencedUrlObject.searchParams.delete("as_js_classic");
592
+ referencedUrlObject.searchParams.delete("as_json_module");
604
593
  const buildUrl = buildUrlsGenerator.generate(
605
594
  referencedUrlObject.href,
606
595
  {
607
596
  urlInfo: rawUrlInfo,
608
- parentUrlInfo,
597
+ ownerUrlInfo: ownerFinalUrlInfo,
609
598
  },
610
599
  );
611
600
  associateBuildUrlAndRawUrl(
@@ -624,7 +613,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
624
613
  }
625
614
  if (reference.type === "sourcemap_comment") {
626
615
  // inherit parent build url
627
- return generateSourcemapFileUrl(reference.parentUrl);
616
+ return generateSourcemapFileUrl(reference.ownerUrlInfo.url);
628
617
  }
629
618
  // files generated during the final graph:
630
619
  // - sourcemaps
@@ -641,7 +630,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
641
630
  if (!reference.generatedUrl.startsWith("file:")) {
642
631
  return null;
643
632
  }
644
- if (reference.isResourceHint) {
633
+ if (reference.isWeak) {
645
634
  return null;
646
635
  }
647
636
  if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
@@ -658,20 +647,33 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
658
647
  generatedUrlObject.searchParams.delete("as_json_module");
659
648
  generatedUrlObject.searchParams.delete("as_css_module");
660
649
  generatedUrlObject.searchParams.delete("as_text_module");
650
+ generatedUrlObject.searchParams.delete("dynamic_import");
661
651
  generatedUrlObject.hash = "";
662
- const generatedUrl = generatedUrlObject.href;
663
- const specifier = asFormattedBuildUrl(generatedUrl, reference);
664
- buildUrls.set(specifier, reference.generatedUrl);
665
- return specifier;
652
+ const buildUrl = generatedUrlObject.href;
653
+ const buildSpecifier = asFormattedBuildSpecifier(
654
+ reference,
655
+ buildUrl,
656
+ );
657
+ buildSpecifierMap.set(buildSpecifier, reference.generatedUrl);
658
+
659
+ if (!versioning || !shouldApplyVersioningOnReference(reference)) {
660
+ return buildSpecifier;
661
+ }
662
+ const buildSpecifierWithVersionPlaceholder =
663
+ buildVersionsManager.generateBuildSpecifierPlaceholder(
664
+ reference,
665
+ buildSpecifier,
666
+ );
667
+ return buildSpecifierWithVersionPlaceholder;
666
668
  },
667
- fetchUrlContent: async (finalUrlInfo, context) => {
669
+ fetchUrlContent: async (finalUrlInfo) => {
668
670
  const fromBundleOrRawGraph = (url) => {
669
671
  const bundleUrlInfo = bundleUrlInfos[url];
670
672
  if (bundleUrlInfo) {
671
673
  return bundleUrlInfo;
672
674
  }
673
675
  const rawUrl = buildDirectoryRedirections.get(url) || url;
674
- const rawUrlInfo = rawGraph.getUrlInfo(rawUrl);
676
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
675
677
  if (!rawUrlInfo) {
676
678
  throw new Error(
677
679
  createDetailedMessage(`Cannot find url`, {
@@ -701,49 +703,63 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
701
703
  }
702
704
  return rawUrlInfo;
703
705
  };
704
- const { reference } = context;
706
+ const { firstReference } = finalUrlInfo;
707
+ // .original reference updated during "postbuild":
708
+ // happens for "js_module_fallback"
709
+ const reference = firstReference.original || firstReference;
705
710
  // reference injected during "postbuild":
706
711
  // - happens for "js_module_fallback" injecting "s.js"
707
712
  if (reference.injected) {
708
- const [ref, rawUrlInfo] = rawGraphKitchen.injectReference({
709
- ...reference,
710
- parentUrl: buildDirectoryRedirections.get(
711
- reference.parentUrl,
712
- ),
713
- });
714
- await rawGraphKitchen.cook(rawUrlInfo, { reference: ref });
715
- return rawUrlInfo;
713
+ const rawReference =
714
+ rawKitchen.graph.rootUrlInfo.dependencies.inject({
715
+ type: reference.type,
716
+ expectedType: reference.expectedType,
717
+ specifier: reference.specifier,
718
+ specifierLine: reference.specifierLine,
719
+ specifierColumn: reference.specifierColumn,
720
+ specifierStart: reference.specifierStart,
721
+ specifierEnd: reference.specifierEnd,
722
+ });
723
+ await rawReference.urlInfo.cook();
724
+ return {
725
+ type: rawReference.urlInfo.type,
726
+ content: rawReference.urlInfo.content,
727
+ contentType: rawReference.urlInfo.contentType,
728
+ originalContent: rawReference.urlInfo.originalContent,
729
+ originalUrl: rawReference.urlInfo.originalUrl,
730
+ sourcemap: rawReference.urlInfo.sourcemap,
731
+ };
716
732
  }
717
733
  if (reference.isInline) {
718
- if (reference.prev && !reference.prev.isInline) {
719
- const urlBeforeRedirect =
720
- findKey(finalRedirections, reference.prev.url) ||
721
- reference.prev.url;
722
- return fromBundleOrRawGraph(urlBeforeRedirect);
734
+ const prevReference = firstReference.prev;
735
+ if (prevReference) {
736
+ if (!prevReference.isInline) {
737
+ // the reference was inlined
738
+ const urlBeforeRedirect =
739
+ findKey(finalRedirections, prevReference.url) ||
740
+ prevReference.url;
741
+ return fromBundleOrRawGraph(urlBeforeRedirect);
742
+ }
743
+ if (buildDirectoryRedirections.has(prevReference.url)) {
744
+ // the prev reference is transformed to fetch underlying resource
745
+ // (getWithoutSearchParam)
746
+ return fromBundleOrRawGraph(prevReference.url);
747
+ }
723
748
  }
724
- return fromBundleOrRawGraph(reference.url);
749
+ return fromBundleOrRawGraph(firstReference.url);
725
750
  }
726
- // reference updated during "postbuild":
727
- // - happens for "js_module_fallback"
728
- if (reference.original) {
729
- return fromBundleOrRawGraph(reference.original.url);
730
- }
731
- return fromBundleOrRawGraph(finalUrlInfo.url);
751
+ return fromBundleOrRawGraph(reference.url);
732
752
  },
733
753
  },
734
754
  {
735
755
  name: "jsenv:optimize",
736
756
  appliesDuring: "build",
737
- transformUrlContent: async (urlInfo, context) => {
738
- await rawGraphKitchen.pluginController.callAsyncHooks(
757
+ transformUrlContent: async (urlInfo) => {
758
+ await rawKitchen.pluginController.callAsyncHooks(
739
759
  "optimizeUrlContent",
740
760
  urlInfo,
741
- context,
742
761
  (optimizeReturnValue) => {
743
- finalGraphKitchen.urlInfoTransformer.applyTransformations(
744
- urlInfo,
745
- optimizeReturnValue,
746
- );
762
+ urlInfo.mutateContent(optimizeReturnValue);
747
763
  },
748
764
  );
749
765
  },
@@ -751,13 +767,29 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
751
767
  ],
752
768
  sourcemaps,
753
769
  sourcemapsSourcesContent,
754
- sourcemapsSourcesRelative: !versioning,
770
+ sourcemapsSourcesRelative: true,
755
771
  outDirectoryUrl: outDirectoryUrl
756
772
  ? new URL("postbuild/", outDirectoryUrl)
757
773
  : undefined,
758
774
  });
775
+ buildVersionsManager = createBuildVersionsManager({
776
+ finalKitchen,
777
+ versioningMethod,
778
+ versionLength,
779
+ canUseImportmap:
780
+ versioningViaImportmap &&
781
+ finalEntryUrls.every((finalEntryUrl) => {
782
+ const finalEntryUrlInfo =
783
+ finalKitchen.graph.getUrlInfo(finalEntryUrl);
784
+ return finalEntryUrlInfo.type === "html";
785
+ }) &&
786
+ rawKitchen.context.isSupportedOnCurrentClients("importmap"),
787
+ getBuildUrlFromBuildSpecifier: (buildSpecifier) =>
788
+ buildSpecifierMap.get(buildSpecifier),
789
+ });
790
+
759
791
  bundle: {
760
- rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
792
+ rawKitchen.pluginController.plugins.forEach((plugin) => {
761
793
  const bundle = plugin.bundle;
762
794
  if (!bundle) {
763
795
  return;
@@ -780,58 +812,60 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
780
812
  bundlers[type] = {
781
813
  plugin,
782
814
  bundleFunction: bundle[type],
783
- urlInfos: [],
815
+ urlInfoMap: new Map(),
784
816
  };
785
817
  });
786
818
  });
787
819
  const addToBundlerIfAny = (rawUrlInfo) => {
788
820
  const bundler = bundlers[rawUrlInfo.type];
789
821
  if (bundler) {
790
- bundler.urlInfos.push(rawUrlInfo);
822
+ bundler.urlInfoMap.set(rawUrlInfo.url, rawUrlInfo);
791
823
  }
792
824
  };
793
- GRAPH_VISITOR.forEach(rawGraph, (rawUrlInfo) => {
794
- // cleanup unused urls (avoid bundling things that are not actually used)
825
+ GRAPH_VISITOR.forEach(rawKitchen.graph, (rawUrlInfo) => {
826
+ // ignore unused urls (avoid bundling things that are not actually used)
795
827
  // happens for:
796
828
  // - js import assertions
797
829
  // - conversion to js classic using ?as_js_classic or ?js_module_fallback
798
- if (!rawGraph.isUsed(rawUrlInfo)) {
799
- rawGraph.deleteUrlInfo(rawUrlInfo.url);
830
+ if (!rawUrlInfo.isUsed()) {
800
831
  return;
801
832
  }
802
833
  if (rawUrlInfo.isEntryPoint) {
803
834
  addToBundlerIfAny(rawUrlInfo);
804
835
  }
805
836
  if (rawUrlInfo.type === "html") {
806
- rawUrlInfo.dependencies.forEach((dependencyUrl) => {
807
- const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl);
808
- if (dependencyUrlInfo.isInline) {
809
- if (dependencyUrlInfo.type === "js_module") {
837
+ rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
838
+ if (referenceToOther.isWeak) {
839
+ return;
840
+ }
841
+ const referencedUrlInfo = referenceToOther.urlInfo;
842
+ if (referencedUrlInfo.isInline) {
843
+ if (referencedUrlInfo.type === "js_module") {
810
844
  // bundle inline script type module deps
811
- dependencyUrlInfo.references.forEach((inlineScriptRef) => {
812
- if (inlineScriptRef.type === "js_import") {
813
- const inlineUrlInfo = rawGraph.getUrlInfo(
814
- inlineScriptRef.url,
815
- );
816
- addToBundlerIfAny(inlineUrlInfo);
817
- }
818
- });
845
+ referencedUrlInfo.referenceToOthersSet.forEach(
846
+ (jsModuleReferenceToOther) => {
847
+ if (jsModuleReferenceToOther.type === "js_import") {
848
+ const inlineUrlInfo = jsModuleReferenceToOther.urlInfo;
849
+ addToBundlerIfAny(inlineUrlInfo);
850
+ }
851
+ },
852
+ );
819
853
  }
820
854
  // inline content cannot be bundled
821
855
  return;
822
856
  }
823
- addToBundlerIfAny(dependencyUrlInfo);
857
+ addToBundlerIfAny(referencedUrlInfo);
824
858
  });
825
- rawUrlInfo.references.forEach((reference) => {
859
+ rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
826
860
  if (
827
- reference.isResourceHint &&
828
- reference.expectedType === "js_module"
861
+ referenceToOther.isResourceHint &&
862
+ referenceToOther.expectedType === "js_module"
829
863
  ) {
830
- const referencedUrlInfo = rawGraph.getUrlInfo(reference.url);
864
+ const referencedUrlInfo = referenceToOther.urlInfo;
831
865
  if (
832
866
  referencedUrlInfo &&
833
867
  // something else than the resource hint is using this url
834
- referencedUrlInfo.dependents.size > 0
868
+ referencedUrlInfo.referenceFromOthersSet.size > 0
835
869
  ) {
836
870
  addToBundlerIfAny(referencedUrlInfo);
837
871
  }
@@ -843,29 +877,25 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
843
877
  // are entry points that should be bundled
844
878
  // For instance we will bundle service worker/workers detected like this
845
879
  if (rawUrlInfo.type === "js_module") {
846
- rawUrlInfo.references.forEach((reference) => {
847
- if (reference.type !== "js_url") {
848
- return;
849
- }
850
- const referencedUrlInfo = rawGraph.getUrlInfo(reference.url);
851
- const bundler = bundlers[referencedUrlInfo.type];
852
- if (!bundler) {
853
- return;
854
- }
855
-
856
- let willAlreadyBeBundled = true;
857
- for (const dependent of referencedUrlInfo.dependents) {
858
- const dependentUrlInfo = rawGraph.getUrlInfo(dependent);
859
- for (const reference of dependentUrlInfo.references) {
860
- if (reference.url === referencedUrlInfo.url) {
861
- willAlreadyBeBundled =
862
- reference.subtype === "import_dynamic" ||
863
- reference.type === "script";
880
+ rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
881
+ if (referenceToOther.type === "js_url") {
882
+ const referencedUrlInfo = referenceToOther.urlInfo;
883
+ for (const referenceFromOther of referencedUrlInfo.referenceFromOthersSet) {
884
+ if (referenceFromOther.url === referencedUrlInfo.url) {
885
+ if (
886
+ referenceFromOther.subtype === "import_dynamic" ||
887
+ referenceFromOther.type === "script"
888
+ ) {
889
+ // will already be bundled
890
+ return;
891
+ }
864
892
  }
865
893
  }
894
+ addToBundlerIfAny(referencedUrlInfo);
895
+ return;
866
896
  }
867
- if (!willAlreadyBeBundled) {
868
- bundler.urlInfos.push(referencedUrlInfo);
897
+ if (referenceToOther.type === "js_inline_content") {
898
+ // we should bundle it too right?
869
899
  }
870
900
  });
871
901
  }
@@ -873,28 +903,23 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
873
903
  await Object.keys(bundlers).reduce(async (previous, type) => {
874
904
  await previous;
875
905
  const bundler = bundlers[type];
876
- const urlInfosToBundle = bundler.urlInfos;
906
+ const urlInfosToBundle = Array.from(bundler.urlInfoMap.values());
877
907
  if (urlInfosToBundle.length === 0) {
878
908
  return;
879
909
  }
880
910
  const bundleTask = createBuildTask(`bundle "${type}"`);
881
911
  try {
882
912
  const bundlerGeneratedUrlInfos =
883
- await rawGraphKitchen.pluginController.callAsyncHook(
913
+ await rawKitchen.pluginController.callAsyncHook(
884
914
  {
885
915
  plugin: bundler.plugin,
886
916
  hookName: "bundle",
887
917
  value: bundler.bundleFunction,
888
918
  },
889
919
  urlInfosToBundle,
890
- {
891
- ...rawGraphKitchen.kitchenContext,
892
- buildDirectoryUrl,
893
- assetsDirectory,
894
- },
895
920
  );
896
921
  Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
897
- const rawUrlInfo = rawGraph.getUrlInfo(url);
922
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(url);
898
923
  const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url];
899
924
  const bundleUrlInfo = {
900
925
  type,
@@ -914,7 +939,8 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
914
939
  };
915
940
  if (bundlerGeneratedUrlInfo.sourceUrls) {
916
941
  bundlerGeneratedUrlInfo.sourceUrls.forEach((sourceUrl) => {
917
- const sourceRawUrlInfo = rawGraph.getUrlInfo(sourceUrl);
942
+ const sourceRawUrlInfo =
943
+ rawKitchen.graph.getUrlInfo(sourceUrl);
918
944
  if (sourceRawUrlInfo) {
919
945
  sourceRawUrlInfo.data.bundled = true;
920
946
  }
@@ -926,7 +952,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
926
952
  bundleRedirections.set(url, buildUrl);
927
953
  if (urlIsInsideOf(url, buildDirectoryUrl)) {
928
954
  if (bundlerGeneratedUrlInfo.data.isDynamicEntry) {
929
- const rawUrlInfo = rawGraph.getUrlInfo(
955
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(
930
956
  bundlerGeneratedUrlInfo.originalUrl,
931
957
  );
932
958
  rawUrlInfo.data.bundled = false;
@@ -972,24 +998,21 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
972
998
  if (outDirectoryUrl) {
973
999
  await ensureEmptyDirectory(new URL(`postbuild/`, outDirectoryUrl));
974
1000
  }
975
- const finalUrlGraphLoader = createUrlGraphLoader(
976
- finalGraphKitchen.kitchenContext,
977
- );
978
- entryUrls.forEach((entryUrl) => {
979
- const [finalEntryReference, finalEntryUrlInfo] =
980
- finalGraphKitchen.kitchenContext.prepareEntryPoint({
1001
+ const finalRootUrlInfo = finalKitchen.graph.rootUrlInfo;
1002
+ await finalRootUrlInfo.dependencies.startCollecting(() => {
1003
+ entryUrls.forEach((entryUrl) => {
1004
+ const entryReference = finalRootUrlInfo.dependencies.found({
981
1005
  trace: { message: `entryPoint` },
982
- parentUrl: sourceDirectoryUrl,
1006
+ isEntryPoint: true,
983
1007
  type: "entry_point",
984
1008
  specifier: entryUrl,
985
1009
  });
986
- finalEntryUrls.push(finalEntryUrlInfo.url);
987
- finalUrlGraphLoader.load(finalEntryUrlInfo, {
988
- reference: finalEntryReference,
1010
+ finalEntryUrls.push(entryReference.url);
989
1011
  });
990
1012
  });
991
- await finalUrlGraphLoader.getAllLoadDonePromise(buildOperation);
992
- await finalGraphKitchen.injectForwardedSideEffectFiles();
1013
+ await finalRootUrlInfo.cookDependencies({
1014
+ operation: buildOperation,
1015
+ });
993
1016
  } catch (e) {
994
1017
  generateBuildGraph.fail();
995
1018
  throw e;
@@ -998,397 +1021,16 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
998
1021
  }
999
1022
  }
1000
1023
 
1001
- const versionMap = new Map();
1002
- const versionedUrlMap = new Map();
1003
1024
  refine: {
1004
- inject_version_in_urls: {
1025
+ apply_versioning: {
1005
1026
  if (!versioning) {
1006
- break inject_version_in_urls;
1027
+ break apply_versioning;
1007
1028
  }
1008
- const versioningTask = createBuildTask("inject version in urls");
1029
+ // see also "New hashing algorithm that "fixes (nearly) everything"
1030
+ // at https://github.com/rollup/rollup/pull/4543
1031
+ const versioningTask = createBuildTask("apply versioning");
1009
1032
  try {
1010
- const canUseImportmap =
1011
- versioningViaImportmap &&
1012
- finalEntryUrls.every((finalEntryUrl) => {
1013
- const finalEntryUrlInfo = finalGraph.getUrlInfo(finalEntryUrl);
1014
- return finalEntryUrlInfo.type === "html";
1015
- }) &&
1016
- finalGraphKitchen.kitchenContext.isSupportedOnCurrentClients(
1017
- "importmap",
1018
- );
1019
- const workerReferenceSet = new Set();
1020
- const isReferencedByWorker = (reference, graph) => {
1021
- if (workerReferenceSet.has(reference)) {
1022
- return true;
1023
- }
1024
- const urlInfo = graph.getUrlInfo(reference.url);
1025
- const dependentWorker = GRAPH_VISITOR.findDependent(
1026
- graph,
1027
- urlInfo,
1028
- (dependentUrlInfo) => {
1029
- return isWebWorkerUrlInfo(dependentUrlInfo);
1030
- },
1031
- );
1032
- if (dependentWorker) {
1033
- workerReferenceSet.add(reference);
1034
- return true;
1035
- }
1036
- return Boolean(dependentWorker);
1037
- };
1038
- const preferWithoutVersioning = (reference) => {
1039
- const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl);
1040
- if (parentUrlInfo.jsQuote) {
1041
- return {
1042
- type: "global",
1043
- source: `${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
1044
- reference.specifier,
1045
- )})+${parentUrlInfo.jsQuote}`,
1046
- };
1047
- }
1048
- if (reference.type === "js_url") {
1049
- return {
1050
- type: "global",
1051
- source: `__v__(${JSON.stringify(reference.specifier)})`,
1052
- };
1053
- }
1054
- if (reference.type === "js_import") {
1055
- if (reference.subtype === "import_dynamic") {
1056
- return {
1057
- type: "global",
1058
- source: `__v__(${JSON.stringify(reference.specifier)})`,
1059
- };
1060
- }
1061
- if (reference.subtype === "import_meta_resolve") {
1062
- return {
1063
- type: "global",
1064
- source: `__v__(${JSON.stringify(reference.specifier)})`,
1065
- };
1066
- }
1067
- if (
1068
- canUseImportmap &&
1069
- !isReferencedByWorker(reference, finalGraph)
1070
- ) {
1071
- return {
1072
- type: "importmap",
1073
- source: JSON.stringify(reference.specifier),
1074
- };
1075
- }
1076
- }
1077
- return null;
1078
- };
1079
-
1080
- // see also https://github.com/rollup/rollup/pull/4543
1081
- const contentVersionMap = new Map();
1082
- const hashCallbacks = [];
1083
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1084
- if (urlInfo.type === "sourcemap") {
1085
- return;
1086
- }
1087
- // ignore:
1088
- // - inline files and data files:
1089
- // they are already taken into account in the file where they appear
1090
- // - ignored files:
1091
- // we don't know their content
1092
- // - unused files without reference
1093
- // File updated such as style.css -> style.css.js or file.js->file.nomodule.js
1094
- // Are used at some point just to be discarded later because they need to be converted
1095
- // There is no need to version them and we could not because the file have been ignored
1096
- // so their content is unknown
1097
- if (urlInfo.isInline) {
1098
- return;
1099
- }
1100
- // urlInfo became inline and is not referenced by something else
1101
- if (urlInfo.url.startsWith("data:")) {
1102
- return;
1103
- }
1104
- if (urlInfo.url.startsWith("ignore:")) {
1105
- return;
1106
- }
1107
- if (urlInfo.dependents.size === 0 && !urlInfo.isEntryPoint) {
1108
- return;
1109
- }
1110
- const urlContent =
1111
- urlInfo.type === "html"
1112
- ? stringifyHtmlAst(
1113
- parseHtmlString(urlInfo.content, {
1114
- storeOriginalPositions: false,
1115
- }),
1116
- {
1117
- cleanupJsenvAttributes: true,
1118
- cleanupPositionAttributes: true,
1119
- },
1120
- )
1121
- : urlInfo.content;
1122
- const contentVersionGenerator = createVersionGenerator();
1123
- contentVersionGenerator.augmentWithContent(urlContent);
1124
- const contentVersion = contentVersionGenerator.generate();
1125
- contentVersionMap.set(urlInfo.url, contentVersion);
1126
- const versionMutations = [];
1127
- const seen = new Set();
1128
- const visitReferences = (urlInfo) => {
1129
- urlInfo.references.forEach((reference) => {
1130
- if (seen.has(reference)) return;
1131
- seen.add(reference);
1132
- const referencedUrlInfo = finalGraph.getUrlInfo(reference.url);
1133
- versionMutations.push(() => {
1134
- const dependencyContentVersion = contentVersionMap.get(
1135
- reference.url,
1136
- );
1137
- if (!dependencyContentVersion) {
1138
- // no content generated for this dependency
1139
- // (inline, data:, ignore:, sourcemap, ...)
1140
- return null;
1141
- }
1142
- if (preferWithoutVersioning(reference)) {
1143
- // when versioning is dynamic no need to take into account
1144
- // happens for:
1145
- // - specifier mapped by window.__v__()
1146
- // - specifier mapped by importmap
1147
- return null;
1148
- }
1149
- return dependencyContentVersion;
1150
- });
1151
- visitReferences(referencedUrlInfo);
1152
- });
1153
- };
1154
- visitReferences(urlInfo);
1155
-
1156
- hashCallbacks.push(() => {
1157
- let version;
1158
- if (versionMutations.length === 0) {
1159
- version = contentVersion;
1160
- } else {
1161
- const versionGenerator = createVersionGenerator();
1162
- versionGenerator.augment(contentVersion);
1163
- versionMutations.forEach((versionMutation) => {
1164
- const value = versionMutation();
1165
- if (value) {
1166
- versionGenerator.augment(value);
1167
- }
1168
- });
1169
- version = versionGenerator.generate();
1170
- }
1171
- versionMap.set(urlInfo.url, version);
1172
- const buildUrlObject = new URL(urlInfo.url);
1173
- // remove ?js_module_fallback
1174
- // this information is already hold into ".nomodule"
1175
- buildUrlObject.searchParams.delete("js_module_fallback");
1176
- buildUrlObject.searchParams.delete("as_js_classic");
1177
- buildUrlObject.searchParams.delete("as_js_module");
1178
- buildUrlObject.searchParams.delete("as_json_module");
1179
- buildUrlObject.searchParams.delete("as_css_module");
1180
- buildUrlObject.searchParams.delete("as_text_module");
1181
- const buildUrl = buildUrlObject.href;
1182
- finalRedirections.set(urlInfo.url, buildUrl);
1183
- versionedUrlMap.set(
1184
- urlInfo.url,
1185
- normalizeUrl(
1186
- injectVersionIntoBuildUrl({
1187
- buildUrl,
1188
- version,
1189
- versioningMethod,
1190
- }),
1191
- ),
1192
- );
1193
- });
1194
- });
1195
- hashCallbacks.forEach((callback) => {
1196
- callback();
1197
- });
1198
-
1199
- const versionMappings = {};
1200
- const versionMappingsOnGlobalMap = new Set();
1201
- const versionMappingsOnImportmap = new Set();
1202
- const versioningKitchen = createKitchen({
1203
- logLevel: logger.level,
1204
- rootDirectoryUrl: buildDirectoryUrl,
1205
- ignore,
1206
- ignoreProtocol: "remove",
1207
- urlGraph: finalGraph,
1208
- build: true,
1209
- runtimeCompat,
1210
- ...contextSharedDuringBuild,
1211
- plugins: [
1212
- jsenvPluginReferenceAnalysis({
1213
- ...referenceAnalysis,
1214
- fetchInlineUrls: false,
1215
- inlineConvertedScript: true, // to be able to version their urls
1216
- allowEscapeForVersioning: true,
1217
- }),
1218
- {
1219
- name: "jsenv:versioning",
1220
- appliesDuring: "build",
1221
- resolveReference: (reference) => {
1222
- const buildUrl = buildUrls.get(reference.specifier);
1223
- if (buildUrl) {
1224
- return buildUrl;
1225
- }
1226
- let urlObject;
1227
- if (reference.specifier[0] === "/") {
1228
- urlObject = new URL(
1229
- reference.specifier.slice(1),
1230
- buildDirectoryUrl,
1231
- );
1232
- } else {
1233
- urlObject = new URL(
1234
- reference.specifier,
1235
- reference.baseUrl || reference.parentUrl,
1236
- );
1237
- }
1238
- const url = urlObject.href;
1239
- // during versioning we revisit the deps
1240
- // but the code used to enforce trailing slash on directories
1241
- // is not applied because "jsenv:file_url_resolution" is not used
1242
- // so here we search if the url with a trailing slash exists
1243
- if (
1244
- reference.type === "filesystem" &&
1245
- !urlObject.pathname.endsWith("/")
1246
- ) {
1247
- const urlWithTrailingSlash = `${url}/`;
1248
- const specifier = findKey(buildUrls, urlWithTrailingSlash);
1249
- if (specifier) {
1250
- return urlWithTrailingSlash;
1251
- }
1252
- }
1253
- return url;
1254
- },
1255
- formatReference: (reference) => {
1256
- if (reference.url.startsWith("ignore:")) {
1257
- return null;
1258
- }
1259
- if (reference.isInline) {
1260
- return null;
1261
- }
1262
- if (reference.url.startsWith("data:")) {
1263
- return null;
1264
- }
1265
- if (reference.isResourceHint) {
1266
- return null;
1267
- }
1268
- // specifier comes from "normalize" hook done a bit earlier in this file
1269
- // we want to get back their build url to access their infos
1270
- const referencedUrlInfo = finalGraph.getUrlInfo(
1271
- reference.url,
1272
- );
1273
- if (!canUseVersionedUrl(referencedUrlInfo)) {
1274
- return reference.specifier;
1275
- }
1276
- const versionedUrl = versionedUrlMap.get(reference.url);
1277
- if (!versionedUrl) {
1278
- // happens for inline content and sourcemaps
1279
- return urlToRelativeUrl(
1280
- referencedUrlInfo.url,
1281
- reference.parentUrl,
1282
- );
1283
- }
1284
- const versionedSpecifier = asFormattedBuildUrl(
1285
- versionedUrl,
1286
- reference,
1287
- );
1288
- versionMappings[reference.specifier] = versionedSpecifier;
1289
- versioningRedirections.set(reference.url, versionedUrl);
1290
- buildUrls.set(versionedSpecifier, versionedUrl);
1291
-
1292
- const withoutVersioning = preferWithoutVersioning(reference);
1293
- if (withoutVersioning) {
1294
- if (withoutVersioning.type === "importmap") {
1295
- versionMappingsOnImportmap.add(reference.specifier);
1296
- } else {
1297
- versionMappingsOnGlobalMap.add(reference.specifier);
1298
- }
1299
- return () => withoutVersioning.source;
1300
- }
1301
- return versionedSpecifier;
1302
- },
1303
- fetchUrlContent: (versionedUrlInfo) => {
1304
- if (versionedUrlInfo.isInline) {
1305
- const versionedUrl = versionedUrlInfo.url;
1306
- const rawUrl = buildDirectoryRedirections.get(versionedUrl);
1307
- const rawUrlInfo = rawGraph.getUrlInfo(rawUrl);
1308
- const finalUrlInfo = finalGraph.getUrlInfo(versionedUrl);
1309
- return {
1310
- content: versionedUrlInfo.content,
1311
- contentType: versionedUrlInfo.contentType,
1312
- originalContent: rawUrlInfo
1313
- ? rawUrlInfo.originalContent
1314
- : undefined,
1315
- sourcemap: finalUrlInfo
1316
- ? finalUrlInfo.sourcemap
1317
- : undefined,
1318
- };
1319
- }
1320
- return versionedUrlInfo;
1321
- },
1322
- },
1323
- ],
1324
- sourcemaps,
1325
- sourcemapsSourcesContent,
1326
- sourcemapsSourcesRelative: true,
1327
- outDirectoryUrl: outDirectoryUrl
1328
- ? new URL("postbuild/", outDirectoryUrl)
1329
- : undefined,
1330
- });
1331
- const versioningUrlGraphLoader = createUrlGraphLoader(
1332
- versioningKitchen.kitchenContext,
1333
- );
1334
- finalEntryUrls.forEach((finalEntryUrl) => {
1335
- const [finalEntryReference, finalEntryUrlInfo] =
1336
- finalGraphKitchen.kitchenContext.prepareEntryPoint({
1337
- trace: { message: `entryPoint` },
1338
- parentUrl: buildDirectoryUrl,
1339
- type: "entry_point",
1340
- specifier: finalEntryUrl,
1341
- });
1342
- versioningUrlGraphLoader.load(finalEntryUrlInfo, {
1343
- reference: finalEntryReference,
1344
- });
1345
- });
1346
- await versioningUrlGraphLoader.getAllLoadDonePromise(buildOperation);
1347
- workerReferenceSet.clear();
1348
- const actions = [];
1349
- const visitors = [];
1350
- if (versionMappingsOnImportmap.size) {
1351
- const versionMappingsNeeded = {};
1352
- versionMappingsOnImportmap.forEach((specifier) => {
1353
- versionMappingsNeeded[specifier] = versionMappings[specifier];
1354
- });
1355
- visitors.push((urlInfo) => {
1356
- if (urlInfo.type === "html" && urlInfo.isEntryPoint) {
1357
- actions.push(async () => {
1358
- await injectVersionMappingsAsImportmap({
1359
- kitchen: finalGraphKitchen,
1360
- urlInfo,
1361
- versionMappings: versionMappingsNeeded,
1362
- });
1363
- });
1364
- }
1365
- });
1366
- }
1367
- if (versionMappingsOnGlobalMap.size) {
1368
- const versionMappingsNeeded = {};
1369
- versionMappingsOnGlobalMap.forEach((specifier) => {
1370
- versionMappingsNeeded[specifier] = versionMappings[specifier];
1371
- });
1372
- visitors.push((urlInfo) => {
1373
- if (urlInfo.isEntryPoint) {
1374
- actions.push(async () => {
1375
- await injectVersionMappingsAsGlobal({
1376
- kitchen: finalGraphKitchen,
1377
- urlInfo,
1378
- versionMappings: versionMappingsNeeded,
1379
- });
1380
- });
1381
- }
1382
- });
1383
- }
1384
- if (visitors.length) {
1385
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1386
- visitors.forEach((visitor) => visitor(urlInfo));
1387
- });
1388
- if (actions.length) {
1389
- await Promise.all(actions.map((action) => action()));
1390
- }
1391
- }
1033
+ await buildVersionsManager.applyVersioning(finalKitchen);
1392
1034
  } catch (e) {
1393
1035
  versioningTask.fail();
1394
1036
  throw e;
@@ -1396,7 +1038,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1396
1038
  versioningTask.done();
1397
1039
  }
1398
1040
  cleanup_jsenv_attributes_from_html: {
1399
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1041
+ GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
1400
1042
  if (!urlInfo.url.startsWith("file:")) {
1401
1043
  return;
1402
1044
  }
@@ -1419,7 +1061,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1419
1061
  */
1420
1062
  resync_resource_hints: {
1421
1063
  const actions = [];
1422
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1064
+ GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
1423
1065
  if (urlInfo.type !== "html") {
1424
1066
  return;
1425
1067
  }
@@ -1447,7 +1089,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1447
1089
  }
1448
1090
  const onBuildUrl = (buildUrl) => {
1449
1091
  const buildUrlInfo = buildUrl
1450
- ? finalGraph.getUrlInfo(buildUrl)
1092
+ ? finalKitchen.graph.getUrlInfo(buildUrl)
1451
1093
  : null;
1452
1094
  if (!buildUrlInfo) {
1453
1095
  logger.warn(
@@ -1458,56 +1100,64 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1458
1100
  });
1459
1101
  return;
1460
1102
  }
1461
- if (buildUrlInfo.dependents.size === 0) {
1103
+ if (!buildUrlInfo.isUsed()) {
1104
+ let rawUrl = buildDirectoryRedirections.get(buildUrl);
1105
+ if (!rawUrl && rawKitchen.graph.getUrlInfo(buildUrl)) {
1106
+ rawUrl = buildUrl;
1107
+ }
1108
+ if (rawUrl) {
1109
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
1110
+ if (rawUrlInfo && rawUrlInfo.data.bundled) {
1111
+ logger.warn(
1112
+ `remove resource hint on "${rawUrl}" because it was bundled`,
1113
+ );
1114
+ mutations.push(() => {
1115
+ removeHtmlNode(node);
1116
+ });
1117
+ return;
1118
+ }
1119
+ }
1462
1120
  logger.warn(
1463
- `remove resource hint because "${href}" not used anymore`,
1121
+ `remove resource hint on "${href}" because it is not used anymore`,
1464
1122
  );
1465
1123
  mutations.push(() => {
1466
1124
  removeHtmlNode(node);
1467
1125
  });
1468
1126
  return;
1469
1127
  }
1470
- const buildUrlFormatted =
1471
- versioningRedirections.get(buildUrlInfo.url) ||
1472
- buildUrlInfo.url;
1473
- const buildSpecifierBeforeRedirect = findKey(
1474
- buildUrls,
1128
+ const buildUrlFormatted = buildUrlInfo.url;
1129
+ const buildSpecifier = findKey(
1130
+ buildSpecifierMap,
1475
1131
  buildUrlFormatted,
1476
1132
  );
1133
+ const buildSpecifierVersioned =
1134
+ buildVersionsManager.getBuildSpecifierVersioned(
1135
+ buildSpecifier,
1136
+ );
1137
+ let specifier = buildSpecifierVersioned || buildSpecifier;
1477
1138
  mutations.push(() => {
1478
1139
  setHtmlNodeAttributes(node, {
1479
- href: buildSpecifierBeforeRedirect,
1140
+ href: specifier,
1480
1141
  ...(buildUrlInfo.type === "js_classic"
1481
1142
  ? { crossorigin: undefined }
1482
1143
  : {}),
1483
1144
  });
1484
1145
  });
1485
- for (const dependencyUrl of buildUrlInfo.dependencies) {
1486
- const dependencyUrlInfo =
1487
- finalGraph.urlInfoMap.get(dependencyUrl);
1488
- if (dependencyUrlInfo.data.generatedToShareCode) {
1489
- hintsToInject[dependencyUrl] = node;
1146
+ for (const referenceToOther of buildUrlInfo.referenceToOthersSet) {
1147
+ const referencedUrlInfo = referenceToOther.urlInfo;
1148
+ if (referencedUrlInfo.data.generatedToShareCode) {
1149
+ hintsToInject[referencedUrlInfo.url] = node;
1490
1150
  }
1491
1151
  }
1492
1152
  };
1493
1153
  if (href.startsWith("file:")) {
1494
1154
  let url = href;
1495
1155
  url = rawRedirections.get(url) || url;
1496
- const rawUrlInfo = rawGraph.getUrlInfo(url);
1497
- if (rawUrlInfo && rawUrlInfo.data.bundled) {
1498
- logger.warn(
1499
- `remove resource hint on "${href}" because it was bundled`,
1500
- );
1501
- mutations.push(() => {
1502
- removeHtmlNode(node);
1503
- });
1504
- } else {
1505
- url = bundleRedirections.get(url) || url;
1506
- url = bundleInternalRedirections.get(url) || url;
1507
- url = finalRedirections.get(url) || url;
1508
- url = findKey(buildDirectoryRedirections, url) || url;
1509
- onBuildUrl(url);
1510
- }
1156
+ url = bundleRedirections.get(url) || url;
1157
+ url = bundleInternalRedirections.get(url) || url;
1158
+ url = finalRedirections.get(url) || url;
1159
+ url = findKey(buildDirectoryRedirections, url) || url;
1160
+ onBuildUrl(url);
1511
1161
  } else {
1512
1162
  onBuildUrl(null);
1513
1163
  }
@@ -1515,21 +1165,23 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1515
1165
  });
1516
1166
  Object.keys(hintsToInject).forEach((urlToHint) => {
1517
1167
  const hintNode = hintsToInject[urlToHint];
1518
- const urlFormatted =
1519
- versioningRedirections.get(urlToHint) || urlToHint;
1520
- const specifierBeforeRedirect = findKey(buildUrls, urlFormatted);
1168
+ const urlFormatted = urlToHint;
1169
+ const buildSpecifierBeforeRedirect = findKey(
1170
+ buildSpecifierMap,
1171
+ urlFormatted,
1172
+ );
1521
1173
  const found = findHtmlNode(htmlAst, (htmlNode) => {
1522
1174
  return (
1523
1175
  htmlNode.nodeName === "link" &&
1524
1176
  getHtmlNodeAttribute(htmlNode, "href") ===
1525
- specifierBeforeRedirect
1177
+ buildSpecifierBeforeRedirect
1526
1178
  );
1527
1179
  });
1528
1180
  if (!found) {
1529
1181
  mutations.push(() => {
1530
1182
  const nodeToInsert = createHtmlNode({
1531
1183
  tagName: "link",
1532
- href: specifierBeforeRedirect,
1184
+ href: buildSpecifierBeforeRedirect,
1533
1185
  rel: getHtmlNodeAttribute(hintNode, "rel"),
1534
1186
  as: getHtmlNodeAttribute(hintNode, "as"),
1535
1187
  type: getHtmlNodeAttribute(hintNode, "type"),
@@ -1542,12 +1194,9 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1542
1194
  if (mutations.length > 0) {
1543
1195
  actions.push(() => {
1544
1196
  mutations.forEach((mutation) => mutation());
1545
- finalGraphKitchen.urlInfoTransformer.applyTransformations(
1546
- urlInfo,
1547
- {
1548
- content: stringifyHtmlAst(htmlAst),
1549
- },
1550
- );
1197
+ urlInfo.mutateContent({
1198
+ content: stringifyHtmlAst(htmlAst),
1199
+ });
1551
1200
  });
1552
1201
  }
1553
1202
  });
@@ -1560,10 +1209,10 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1560
1209
  }
1561
1210
  delete_unused_urls: {
1562
1211
  const actions = [];
1563
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1564
- if (!finalGraph.isUsed(urlInfo)) {
1212
+ GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
1213
+ if (!urlInfo.isUsed()) {
1565
1214
  actions.push(() => {
1566
- finalGraph.deleteUrlInfo(urlInfo.url);
1215
+ urlInfo.deleteFromGraph();
1567
1216
  });
1568
1217
  }
1569
1218
  });
@@ -1571,7 +1220,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1571
1220
  }
1572
1221
  inject_urls_in_service_workers: {
1573
1222
  const serviceWorkerEntryUrlInfos = GRAPH_VISITOR.filter(
1574
- finalGraph,
1223
+ finalKitchen.graph,
1575
1224
  (finalUrlInfo) => {
1576
1225
  return (
1577
1226
  finalUrlInfo.subtype === "service_worker" &&
@@ -1584,7 +1233,10 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1584
1233
  "inject urls in service worker",
1585
1234
  );
1586
1235
  const serviceWorkerResources = {};
1587
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1236
+ GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
1237
+ if (urlInfo.isRoot) {
1238
+ return;
1239
+ }
1588
1240
  if (!urlInfo.url.startsWith("file:")) {
1589
1241
  return;
1590
1242
  }
@@ -1595,50 +1247,40 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1595
1247
  // when url is not versioned we compute a "version" for that url anyway
1596
1248
  // so that service worker source still changes and navigator
1597
1249
  // detect there is a change
1598
- const specifier = findKey(buildUrls, urlInfo.url);
1599
- serviceWorkerResources[specifier] = {
1600
- version: versionMap.get(urlInfo.url),
1250
+ const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
1251
+ serviceWorkerResources[buildSpecifier] = {
1252
+ version: buildVersionsManager.getVersion(urlInfo),
1601
1253
  };
1602
1254
  return;
1603
1255
  }
1604
- const specifier = findKey(buildUrls, urlInfo.url);
1605
- const versionedUrl = versionedUrlMap.get(urlInfo.url);
1606
- const versionedSpecifier = findKey(buildUrls, versionedUrl);
1607
- serviceWorkerResources[specifier] = {
1608
- version: versionMap.get(urlInfo.url),
1609
- versionedUrl: versionedSpecifier,
1256
+ const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
1257
+ const buildSpecifierVersioned =
1258
+ buildVersionsManager.getBuildSpecifierVersioned(buildSpecifier);
1259
+ serviceWorkerResources[buildSpecifier] = {
1260
+ version: buildVersionsManager.getVersion(urlInfo),
1261
+ versionedUrl: buildSpecifierVersioned,
1610
1262
  };
1611
1263
  });
1612
- serviceWorkerEntryUrlInfos.forEach((serviceWorkerEntryUrlInfo) => {
1613
- const magicSource = createMagicSource(
1614
- serviceWorkerEntryUrlInfo.content,
1615
- );
1264
+ for (const serviceWorkerEntryUrlInfo of serviceWorkerEntryUrlInfos) {
1616
1265
  const serviceWorkerResourcesWithoutSwScriptItSelf = {
1617
1266
  ...serviceWorkerResources,
1618
1267
  };
1619
- const serviceWorkerSpecifier = findKey(
1620
- buildUrls,
1268
+ const serviceWorkerBuildSpecifier = findKey(
1269
+ buildSpecifierMap,
1621
1270
  serviceWorkerEntryUrlInfo.url,
1622
1271
  );
1623
1272
  delete serviceWorkerResourcesWithoutSwScriptItSelf[
1624
- serviceWorkerSpecifier
1273
+ serviceWorkerBuildSpecifier
1625
1274
  ];
1626
- magicSource.prepend(
1627
- `\nself.resourcesFromJsenvBuild = ${JSON.stringify(
1275
+ await prependContent(serviceWorkerEntryUrlInfo, {
1276
+ type: "js_classic",
1277
+ content: `\nself.resourcesFromJsenvBuild = ${JSON.stringify(
1628
1278
  serviceWorkerResourcesWithoutSwScriptItSelf,
1629
1279
  null,
1630
1280
  " ",
1631
1281
  )};\n`,
1632
- );
1633
- const { content, sourcemap } = magicSource.toContentAndSourcemap();
1634
- finalGraphKitchen.urlInfoTransformer.applyTransformations(
1635
- serviceWorkerEntryUrlInfo,
1636
- {
1637
- content,
1638
- sourcemap,
1639
- },
1640
- );
1641
- });
1282
+ });
1283
+ }
1642
1284
  urlsInjectionInSw.done();
1643
1285
  }
1644
1286
  buildOperation.throwIfAborted();
@@ -1658,7 +1300,10 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1658
1300
  const buildRelativeUrl = urlToRelativeUrl(url, buildDirectoryUrl);
1659
1301
  return buildRelativeUrl;
1660
1302
  };
1661
- GRAPH_VISITOR.forEach(finalGraph, (urlInfo) => {
1303
+ GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
1304
+ if (urlInfo.isRoot) {
1305
+ return;
1306
+ }
1662
1307
  if (!urlInfo.url.startsWith("file:")) {
1663
1308
  return;
1664
1309
  }
@@ -1670,18 +1315,29 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1670
1315
  buildContents[buildRelativeUrl] = urlInfo.content;
1671
1316
  buildInlineRelativeUrls.push(buildRelativeUrl);
1672
1317
  } else {
1673
- const versionedUrl = versionedUrlMap.get(urlInfo.url);
1674
- if (versionedUrl && canUseVersionedUrl(urlInfo)) {
1675
- const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
1676
- const versionedBuildRelativeUrl = getBuildRelativeUrl(versionedUrl);
1318
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
1319
+ if (
1320
+ buildVersionsManager.getVersion(urlInfo) &&
1321
+ canUseVersionedUrl(urlInfo)
1322
+ ) {
1323
+ const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
1324
+ const buildSpecifierVersioned =
1325
+ buildVersionsManager.getBuildSpecifierVersioned(buildSpecifier);
1326
+ const buildUrlVersioned = asBuildUrlVersioned({
1327
+ buildSpecifierVersioned,
1328
+ buildDirectoryUrl,
1329
+ });
1330
+ const buildRelativeUrlVersioned = urlToRelativeUrl(
1331
+ buildUrlVersioned,
1332
+ buildDirectoryUrl,
1333
+ );
1677
1334
  if (versioningMethod === "search_param") {
1678
1335
  buildContents[buildRelativeUrl] = urlInfo.content;
1679
1336
  } else {
1680
- buildContents[versionedBuildRelativeUrl] = urlInfo.content;
1337
+ buildContents[buildRelativeUrlVersioned] = urlInfo.content;
1681
1338
  }
1682
- buildManifest[buildRelativeUrl] = versionedBuildRelativeUrl;
1339
+ buildManifest[buildRelativeUrl] = buildRelativeUrlVersioned;
1683
1340
  } else {
1684
- const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
1685
1341
  buildContents[buildRelativeUrl] = urlInfo.content;
1686
1342
  }
1687
1343
  }
@@ -1719,7 +1375,9 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1719
1375
  }
1720
1376
  writingFiles.done();
1721
1377
  }
1722
- logger.info(createUrlGraphSummary(finalGraph, { title: "build files" }));
1378
+ logger.info(
1379
+ createUrlGraphSummary(finalKitchen.graph, { title: "build files" }),
1380
+ );
1723
1381
  return {
1724
1382
  buildFileContents,
1725
1383
  buildInlineContents,
@@ -1805,22 +1463,48 @@ const findKey = (map, value) => {
1805
1463
  return undefined;
1806
1464
  };
1807
1465
 
1808
- const injectVersionIntoBuildUrl = ({ buildUrl, version, versioningMethod }) => {
1809
- if (versioningMethod === "search_param") {
1810
- return injectQueryParams(buildUrl, {
1811
- v: version,
1812
- });
1466
+ const shouldApplyVersioningOnReference = (reference) => {
1467
+ if (reference.isInline) {
1468
+ return false;
1469
+ }
1470
+ if (reference.next && reference.next.isInline) {
1471
+ return false;
1813
1472
  }
1814
- const basename = urlToBasename(buildUrl);
1815
- const extension = urlToExtension(buildUrl);
1816
- const versionedFilename = `${basename}-${version}${extension}`;
1817
- const versionedUrl = setUrlFilename(buildUrl, versionedFilename);
1818
- return versionedUrl;
1473
+ // specifier comes from "normalize" hook done a bit earlier in this file
1474
+ // we want to get back their build url to access their infos
1475
+ const referencedUrlInfo = reference.urlInfo;
1476
+ if (!canUseVersionedUrl(referencedUrlInfo)) {
1477
+ return false;
1478
+ }
1479
+ if (referencedUrlInfo.type === "sourcemap") {
1480
+ return false;
1481
+ }
1482
+ return true;
1819
1483
  };
1820
1484
 
1821
1485
  const canUseVersionedUrl = (urlInfo) => {
1486
+ if (urlInfo.isRoot) {
1487
+ return false;
1488
+ }
1822
1489
  if (urlInfo.isEntryPoint) {
1823
1490
  return false;
1824
1491
  }
1825
1492
  return urlInfo.type !== "webmanifest";
1826
1493
  };
1494
+
1495
+ const asBuildUrlVersioned = ({
1496
+ buildSpecifierVersioned,
1497
+ buildDirectoryUrl,
1498
+ }) => {
1499
+ if (buildSpecifierVersioned[0] === "/") {
1500
+ return new URL(buildSpecifierVersioned.slice(1), buildDirectoryUrl).href;
1501
+ }
1502
+ const buildUrl = new URL(buildSpecifierVersioned, buildDirectoryUrl).href;
1503
+ if (buildUrl.startsWith(buildDirectoryUrl)) {
1504
+ return buildUrl;
1505
+ }
1506
+ // it's likely "base" parameter was set to an url origin like "https://cdn.example.com"
1507
+ // let's move url to build directory
1508
+ const { pathname, search, hash } = new URL(buildSpecifierVersioned);
1509
+ return `${buildDirectoryUrl}${pathname}${search}${hash}`;
1510
+ };