@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
@@ -0,0 +1,713 @@
1
+ import {
2
+ getCallerPosition,
3
+ stringifyUrlSite,
4
+ generateInlineContentUrl,
5
+ urlToBasename,
6
+ urlToExtension,
7
+ } from "@jsenv/urls";
8
+
9
+ import { isWebWorkerEntryPointReference } from "../web_workers.js";
10
+ import { prependContent } from "../prepend_content.js";
11
+ import { GRAPH_VISITOR } from "./url_graph_visitor.js";
12
+
13
+ export const createDependencies = (ownerUrlInfo) => {
14
+ const { referenceToOthersSet } = ownerUrlInfo;
15
+
16
+ const startCollecting = async (callback) => {
17
+ const prevReferenceToOthersSet = new Set(referenceToOthersSet);
18
+ referenceToOthersSet.clear();
19
+
20
+ const stopCollecting = () => {
21
+ for (const prevReferenceToOther of prevReferenceToOthersSet) {
22
+ applyDependencyRemovalEffects(prevReferenceToOther);
23
+ }
24
+ prevReferenceToOthersSet.clear();
25
+ };
26
+
27
+ try {
28
+ await callback();
29
+ } finally {
30
+ // finally to ensure reference are updated even in case of error
31
+ stopCollecting();
32
+ }
33
+ };
34
+
35
+ const createResolveAndFinalize = (props) => {
36
+ const originalReference = createReference({
37
+ ownerUrlInfo,
38
+ ...props,
39
+ });
40
+ const reference = originalReference.resolve();
41
+ reference.finalize();
42
+ return reference;
43
+ };
44
+
45
+ const found = ({ trace, ...rest }) => {
46
+ if (trace === undefined) {
47
+ trace = traceFromUrlSite(
48
+ adjustUrlSite(ownerUrlInfo, {
49
+ url: ownerUrlInfo.url,
50
+ line: rest.specifierLine,
51
+ column: rest.specifierColumn,
52
+ }),
53
+ );
54
+ }
55
+ const reference = createResolveAndFinalize({
56
+ trace,
57
+ ...rest,
58
+ });
59
+ return reference;
60
+ };
61
+ const foundInline = ({
62
+ isOriginalPosition,
63
+ specifierLine,
64
+ specifierColumn,
65
+ ...rest
66
+ }) => {
67
+ const parentUrl = isOriginalPosition
68
+ ? ownerUrlInfo.url
69
+ : ownerUrlInfo.generatedUrl;
70
+ const parentContent = isOriginalPosition
71
+ ? ownerUrlInfo.originalContent
72
+ : ownerUrlInfo.content;
73
+ const reference = createResolveAndFinalize({
74
+ trace: traceFromUrlSite({
75
+ url: parentUrl,
76
+ content: parentContent,
77
+ line: specifierLine,
78
+ column: specifierColumn,
79
+ }),
80
+ isOriginalPosition,
81
+ specifierLine,
82
+ specifierColumn,
83
+ isInline: true,
84
+ ...rest,
85
+ });
86
+ return reference;
87
+ };
88
+ // side effect file
89
+ const foundSideEffectFile = async ({ sideEffectFileUrl, trace, ...rest }) => {
90
+ if (trace === undefined) {
91
+ const { url, line, column } = getCallerPosition();
92
+ trace = traceFromUrlSite({
93
+ url,
94
+ line,
95
+ column,
96
+ });
97
+ }
98
+ const sideEffectFileReference = ownerUrlInfo.dependencies.inject({
99
+ trace,
100
+ type: "side_effect_file",
101
+ specifier: sideEffectFileUrl,
102
+ ...rest,
103
+ });
104
+ const parentUrlInfo = ownerUrlInfo.findParentIfInline() || ownerUrlInfo;
105
+
106
+ const associateIfReferencedBy = (urlInfo) => {
107
+ for (const referenceToOther of urlInfo.referenceToOthersSet) {
108
+ if (referenceToOther === sideEffectFileReference) {
109
+ continue;
110
+ }
111
+ if (referenceToOther.url === sideEffectFileUrl) {
112
+ // consider this reference becomes the last reference
113
+ // this ensure this ref is properly detected as inlined by urlInfo.isUsed()
114
+ sideEffectFileReference.next =
115
+ referenceToOther.next || referenceToOther;
116
+ return true;
117
+ }
118
+ if (
119
+ referenceToOther.original &&
120
+ referenceToOther.original.url === sideEffectFileUrl
121
+ ) {
122
+ // consider this reference becomes the last reference
123
+ // this ensure this ref is properly detected as inlined by urlInfo.isUsed()
124
+ sideEffectFileReference.next =
125
+ referenceToOther.next || referenceToOther;
126
+ return true;
127
+ }
128
+ }
129
+ return false;
130
+ };
131
+
132
+ const injectAsBannerCodeBeforeFinalize = (urlInfoReceiver) => {
133
+ const basename = urlToBasename(sideEffectFileUrl);
134
+ const inlineUrl = generateInlineContentUrl({
135
+ url: urlInfoReceiver.url,
136
+ basename,
137
+ extension: urlToExtension(sideEffectFileUrl),
138
+ });
139
+ const sideEffectFileReferenceInlined = sideEffectFileReference.inline({
140
+ ownerUrlInfo: urlInfoReceiver,
141
+ trace,
142
+ type: "side_effect_file",
143
+ specifier: inlineUrl,
144
+ });
145
+ urlInfoReceiver.addContentTransformationCallback(async () => {
146
+ await sideEffectFileReferenceInlined.urlInfo.cook();
147
+ await prependContent(
148
+ urlInfoReceiver,
149
+ sideEffectFileReferenceInlined.urlInfo,
150
+ );
151
+ });
152
+ };
153
+
154
+ // When possible we inject code inside the file in a common ancestor
155
+ // -> less duplication
156
+
157
+ // During dev:
158
+ // during dev cooking files is incremental
159
+ // so HTML/JS is already executed by the browser
160
+ // we can't late inject into entry point
161
+ if (ownerUrlInfo.context.dev) {
162
+ if (associateIfReferencedBy(ownerUrlInfo)) {
163
+ return;
164
+ }
165
+ const dependentReferencingThatFile = GRAPH_VISITOR.findDependent(
166
+ parentUrlInfo,
167
+ (ancestorUrlInfo) => {
168
+ if (ancestorUrlInfo.isRoot) {
169
+ return false;
170
+ }
171
+ return associateIfReferencedBy(ancestorUrlInfo);
172
+ },
173
+ );
174
+ if (dependentReferencingThatFile) {
175
+ return;
176
+ }
177
+ injectAsBannerCodeBeforeFinalize(parentUrlInfo);
178
+ return;
179
+ }
180
+
181
+ // During build:
182
+ // during build, files are not executed so it's
183
+ // possible to inject reference when discovering a side effect file
184
+ if (associateIfReferencedBy(ownerUrlInfo)) {
185
+ return;
186
+ }
187
+ // The thing to do here is to inject side effect file into entry point
188
+ // only when:
189
+ // - entry point does not already has it
190
+ // - nothing between entry point and the file has it
191
+ const entryPoints = parentUrlInfo.graph.getEntryPoints();
192
+ for (const entryPointUrlInfo of entryPoints) {
193
+ if (associateIfReferencedBy(entryPointUrlInfo)) {
194
+ continue;
195
+ }
196
+ if (parentUrlInfo.isEntryPoint) {
197
+ injectAsBannerCodeBeforeFinalize(entryPointUrlInfo);
198
+ continue;
199
+ }
200
+ let found = false;
201
+ GRAPH_VISITOR.findDependency(entryPointUrlInfo, (dependencyUrlInfo) => {
202
+ if (associateIfReferencedBy(dependencyUrlInfo)) {
203
+ found = true;
204
+ return true;
205
+ }
206
+ if (dependencyUrlInfo === parentUrlInfo) {
207
+ return true;
208
+ }
209
+ return false;
210
+ });
211
+ if (!found) {
212
+ injectAsBannerCodeBeforeFinalize(entryPointUrlInfo);
213
+ }
214
+ }
215
+ };
216
+
217
+ const inject = ({ trace, ...rest }) => {
218
+ if (trace === undefined) {
219
+ const { url, line, column } = getCallerPosition();
220
+ trace = traceFromUrlSite({
221
+ url,
222
+ line,
223
+ column,
224
+ });
225
+ }
226
+ const reference = createResolveAndFinalize({
227
+ trace,
228
+ injected: true,
229
+ ...rest,
230
+ });
231
+ return reference;
232
+ };
233
+
234
+ return {
235
+ startCollecting,
236
+ createResolveAndFinalize,
237
+ found,
238
+ foundInline,
239
+ foundSideEffectFile,
240
+ inject,
241
+ };
242
+ };
243
+
244
+ /*
245
+ * - "http_request"
246
+ * - "entry_point"
247
+ * - "link_href"
248
+ * - "style"
249
+ * - "script"
250
+ * - "a_href"
251
+ * - "iframe_src
252
+ * - "img_src"
253
+ * - "img_srcset"
254
+ * - "source_src"
255
+ * - "source_srcset"
256
+ * - "image_href"
257
+ * - "use_href"
258
+ * - "css_@import"
259
+ * - "css_url"
260
+ * - "js_import"
261
+ * - "js_import_script"
262
+ * - "js_url"
263
+ * - "js_inline_content"
264
+ * - "sourcemap_comment"
265
+ * - "webmanifest_icon_src"
266
+ * - "package_json"
267
+ * - "side_effect_file"
268
+ * */
269
+ const createReference = ({
270
+ ownerUrlInfo,
271
+ data = {},
272
+ trace,
273
+ type,
274
+ subtype,
275
+ expectedContentType,
276
+ expectedType,
277
+ expectedSubtype,
278
+ filename,
279
+ integrity,
280
+ crossorigin,
281
+ specifier,
282
+ specifierStart,
283
+ specifierEnd,
284
+ specifierLine,
285
+ specifierColumn,
286
+ baseUrl,
287
+ isOriginalPosition,
288
+ isEntryPoint = false,
289
+ isResourceHint = false,
290
+ // implicit references are not real references
291
+ // they represent an abstract relationship
292
+ isImplicit = false,
293
+ // weak references cannot keep the corresponding url info alive
294
+ // there must be an other reference to keep the url info alive
295
+ // an url referenced solely by weak references is:
296
+ // - not written in build directory
297
+ // - can be removed from graph during dev/build
298
+ // - not cooked until referenced by a strong reference
299
+ isWeak = false,
300
+ hasVersioningEffect = false,
301
+ version = null,
302
+ injected = false,
303
+ isInline = false,
304
+ content,
305
+ contentType,
306
+ leadsToADirectory = false,
307
+ debug = false,
308
+ original = null,
309
+ prev = null,
310
+ next = null,
311
+ url = null,
312
+ searchParams = null,
313
+ generatedUrl = null,
314
+ generatedSpecifier = null,
315
+ urlInfo = null,
316
+ escape = null,
317
+ importAttributes,
318
+ astInfo = {},
319
+ mutation,
320
+ }) => {
321
+ if (typeof specifier !== "string") {
322
+ if (specifier instanceof URL) {
323
+ specifier = specifier.href;
324
+ } else {
325
+ throw new TypeError(`"specifier" must be a string, got ${specifier}`);
326
+ }
327
+ }
328
+ const reference = {
329
+ ownerUrlInfo,
330
+ original,
331
+ prev,
332
+ next,
333
+ data,
334
+ trace,
335
+ url,
336
+ urlInfo,
337
+ searchParams,
338
+ generatedUrl,
339
+ generatedSpecifier,
340
+ type,
341
+ subtype,
342
+ expectedContentType,
343
+ expectedType,
344
+ expectedSubtype,
345
+ filename,
346
+ integrity,
347
+ crossorigin,
348
+ specifier,
349
+ specifierStart,
350
+ specifierEnd,
351
+ specifierLine,
352
+ specifierColumn,
353
+ isOriginalPosition,
354
+ baseUrl,
355
+ isEntryPoint,
356
+ isResourceHint,
357
+ isImplicit,
358
+ implicitReferenceSet: new Set(),
359
+ isWeak,
360
+ hasVersioningEffect,
361
+ version,
362
+ injected,
363
+ timing: {},
364
+ leadsToADirectory,
365
+ debug,
366
+ // for inline resources the reference contains the content
367
+ isInline,
368
+ content,
369
+ contentType,
370
+ escape,
371
+ // used mostly by worker and import assertions
372
+ astInfo,
373
+ importAttributes,
374
+ mutation,
375
+ };
376
+
377
+ reference.resolve = () => {
378
+ const resolvedReference =
379
+ reference.ownerUrlInfo.context.resolveReference(reference);
380
+ return resolvedReference;
381
+ };
382
+
383
+ reference.redirect = (url, props = {}) => {
384
+ const redirectedProps = getRedirectedReferenceProps(reference, url);
385
+ const referenceRedirected = createReference({
386
+ ...redirectedProps,
387
+ ...props,
388
+ });
389
+ reference.next = referenceRedirected;
390
+ return referenceRedirected;
391
+ };
392
+
393
+ reference.finalize = () => {
394
+ if (reference.urlInfo) {
395
+ return;
396
+ }
397
+ const kitchen = ownerUrlInfo.kitchen;
398
+ const urlInfo = kitchen.graph.reuseOrCreateUrlInfo(reference);
399
+ reference.urlInfo = urlInfo;
400
+ addDependency(reference);
401
+ ownerUrlInfo.context.finalizeReference(reference);
402
+ };
403
+
404
+ // "formatReferencedUrl" can be async BUT this is an exception
405
+ // for most cases it will be sync. We want to favor the sync signature to keep things simpler
406
+ // The only case where it needs to be async is when
407
+ // the specifier is a `data:*` url
408
+ // in this case we'll wait for the promise returned by
409
+ // "formatReferencedUrl"
410
+ reference.readGeneratedSpecifier = () => {
411
+ if (reference.generatedSpecifier.then) {
412
+ return reference.generatedSpecifier.then((value) => {
413
+ reference.generatedSpecifier = value;
414
+ return value;
415
+ });
416
+ }
417
+ return reference.generatedSpecifier;
418
+ };
419
+
420
+ reference.inline = ({
421
+ line,
422
+ column,
423
+ // when urlInfo is given it means reference is moved into an other file
424
+ ownerUrlInfo = reference.ownerUrlInfo,
425
+ ...props
426
+ }) => {
427
+ const trace = traceFromUrlSite({
428
+ url:
429
+ ownerUrlInfo === undefined
430
+ ? isOriginalPosition
431
+ ? reference.ownerUrlInfo.url
432
+ : reference.ownerUrlInfo.generatedUrl
433
+ : reference.ownerUrlInfo.url,
434
+ content:
435
+ ownerUrlInfo === undefined
436
+ ? isOriginalPosition
437
+ ? reference.ownerUrlInfo.originalContent
438
+ : reference.ownerUrlInfo.content
439
+ : ownerUrlInfo.content,
440
+ line,
441
+ column,
442
+ });
443
+ const inlineCopy = ownerUrlInfo.dependencies.createResolveAndFinalize({
444
+ isInline: true,
445
+ original: reference.original || reference,
446
+ prev: reference,
447
+ trace,
448
+ expectedType: reference.expectedType,
449
+ ...props,
450
+ });
451
+ // the previous reference stays alive so that even after inlining
452
+ // updating the file will invalidate the other file where it was inlined
453
+ reference.next = inlineCopy;
454
+ return inlineCopy;
455
+ };
456
+
457
+ reference.addImplicit = (props) => {
458
+ const implicitReference = ownerUrlInfo.dependencies.inject({
459
+ ...props,
460
+ isImplicit: true,
461
+ });
462
+ reference.implicitReferenceSet.add(implicitReference);
463
+ return implicitReference;
464
+ };
465
+
466
+ reference.remove = () => removeDependency(reference);
467
+
468
+ // Object.preventExtensions(reference) // useful to ensure all properties are declared here
469
+ return reference;
470
+ };
471
+
472
+ const addDependency = (reference) => {
473
+ const { ownerUrlInfo } = reference;
474
+ if (ownerUrlInfo.referenceToOthersSet.has(reference)) {
475
+ return;
476
+ }
477
+ if (!canAddOrRemoveReference(reference)) {
478
+ throw new Error(
479
+ `cannot add reference for content already sent to the browser
480
+ --- reference url ---
481
+ ${reference.url}
482
+ --- content url ---
483
+ ${ownerUrlInfo.url}`,
484
+ );
485
+ }
486
+ ownerUrlInfo.referenceToOthersSet.add(reference);
487
+ if (reference.isImplicit) {
488
+ // an implicit reference is a reference that does not explicitely appear in the file
489
+ // but has an impact on the file
490
+ // -> package.json on import resolution for instance
491
+ // in that case:
492
+ // - file depends on the implicit file (it must autoreload if package.json is modified)
493
+ // - cache validity for the file depends on the implicit file (it must be re-cooked if package.json is modified)
494
+ ownerUrlInfo.implicitUrlSet.add(reference.url);
495
+ if (ownerUrlInfo.isInline) {
496
+ const parentUrlInfo = ownerUrlInfo.graph.getUrlInfo(
497
+ ownerUrlInfo.inlineUrlSite.url,
498
+ );
499
+ parentUrlInfo.implicitUrlSet.add(reference.url);
500
+ }
501
+ }
502
+ const referencedUrlInfo = reference.urlInfo;
503
+ referencedUrlInfo.referenceFromOthersSet.add(reference);
504
+ applyReferenceEffectsOnUrlInfo(reference);
505
+ for (const implicitRef of reference.implicitReferenceSet) {
506
+ addDependency(implicitRef);
507
+ }
508
+ };
509
+
510
+ const removeDependency = (reference) => {
511
+ const { ownerUrlInfo } = reference;
512
+ if (!ownerUrlInfo.referenceToOthersSet.has(reference)) {
513
+ return false;
514
+ }
515
+ if (!canAddOrRemoveReference(reference)) {
516
+ throw new Error(
517
+ `cannot remove reference for content already sent to the browser
518
+ --- reference url ---
519
+ ${reference.url}
520
+ --- content url ---
521
+ ${ownerUrlInfo.url}`,
522
+ );
523
+ }
524
+ for (const implicitRef of reference.implicitReferenceSet) {
525
+ implicitRef.remove();
526
+ }
527
+ ownerUrlInfo.referenceToOthersSet.delete(reference);
528
+ return applyDependencyRemovalEffects(reference);
529
+ };
530
+
531
+ const canAddOrRemoveReference = (reference) => {
532
+ if (reference.isWeak || reference.isImplicit) {
533
+ // weak and implicit references have no restrictions
534
+ // because they are not actual references with an influence on content
535
+ return true;
536
+ }
537
+ const { ownerUrlInfo } = reference;
538
+ if (ownerUrlInfo.context.build) {
539
+ // during build url content is not executed
540
+ // it's still possible to mutate references safely
541
+ return true;
542
+ }
543
+ if (!ownerUrlInfo.contentFinalized) {
544
+ return true;
545
+ }
546
+ if (ownerUrlInfo.isRoot) {
547
+ // the root urlInfo is abstract, there is no real file behind it
548
+ return true;
549
+ }
550
+ if (reference.type === "http_request") {
551
+ // reference created to http requests are abstract concepts
552
+ return true;
553
+ }
554
+ return false;
555
+ };
556
+
557
+ const applyDependencyRemovalEffects = (reference) => {
558
+ const { ownerUrlInfo } = reference;
559
+ const { referenceToOthersSet } = ownerUrlInfo;
560
+
561
+ if (reference.isImplicit && !reference.isInline) {
562
+ let hasAnOtherImplicitRef = false;
563
+ for (const referenceToOther of referenceToOthersSet) {
564
+ if (
565
+ referenceToOther.isImplicit &&
566
+ referenceToOther.url === reference.url
567
+ ) {
568
+ hasAnOtherImplicitRef = true;
569
+ break;
570
+ }
571
+ }
572
+ if (!hasAnOtherImplicitRef) {
573
+ ownerUrlInfo.implicitUrlSet.delete(reference.url);
574
+ }
575
+ }
576
+
577
+ const prevReference = reference.prev;
578
+ const nextReference = reference.next;
579
+ if (prevReference && nextReference) {
580
+ nextReference.prev = prevReference;
581
+ prevReference.next = nextReference;
582
+ } else if (prevReference) {
583
+ prevReference.next = null;
584
+ } else if (nextReference) {
585
+ nextReference.original = null;
586
+ nextReference.prev = null;
587
+ }
588
+
589
+ const referencedUrlInfo = reference.urlInfo;
590
+ referencedUrlInfo.referenceFromOthersSet.delete(reference);
591
+
592
+ const firstReferenceFromOther =
593
+ referencedUrlInfo.getFirstReferenceFromOther();
594
+ if (firstReferenceFromOther) {
595
+ // either applying new ref should override old ref
596
+ // or we should first remove effects before adding new ones
597
+ // for now we just set firstReference to null
598
+ if (reference === referencedUrlInfo.firstReference) {
599
+ referencedUrlInfo.firstReference = null;
600
+ applyReferenceEffectsOnUrlInfo(firstReferenceFromOther);
601
+ }
602
+ return false;
603
+ }
604
+ if (reference.type !== "http_request") {
605
+ referencedUrlInfo.deleteFromGraph(reference);
606
+ return true;
607
+ }
608
+ return false;
609
+ };
610
+
611
+ const traceFromUrlSite = (urlSite) => {
612
+ return {
613
+ message: stringifyUrlSite(urlSite),
614
+ url: urlSite.url,
615
+ line: urlSite.line,
616
+ column: urlSite.column,
617
+ };
618
+ };
619
+
620
+ const adjustUrlSite = (urlInfo, { url, line, column }) => {
621
+ const isOriginal = url === urlInfo.url;
622
+ const adjust = (urlSite, urlInfo) => {
623
+ if (!urlSite.isOriginal) {
624
+ return urlSite;
625
+ }
626
+ const inlineUrlSite = urlInfo.inlineUrlSite;
627
+ if (!inlineUrlSite) {
628
+ return urlSite;
629
+ }
630
+ const parentUrlInfo = urlInfo.graph.getUrlInfo(inlineUrlSite.url);
631
+ return adjust(
632
+ {
633
+ isOriginal: true,
634
+ url: inlineUrlSite.url,
635
+ content: inlineUrlSite.content,
636
+ line:
637
+ inlineUrlSite.line === undefined
638
+ ? urlSite.line
639
+ : inlineUrlSite.line + urlSite.line,
640
+ column:
641
+ inlineUrlSite.column === undefined
642
+ ? urlSite.column
643
+ : inlineUrlSite.column + urlSite.column,
644
+ },
645
+ parentUrlInfo,
646
+ );
647
+ };
648
+ return adjust(
649
+ {
650
+ isOriginal,
651
+ url,
652
+ content: isOriginal ? urlInfo.originalContent : urlInfo.content,
653
+ line,
654
+ column,
655
+ },
656
+ urlInfo,
657
+ );
658
+ };
659
+
660
+ const getRedirectedReferenceProps = (reference, url) => {
661
+ const redirectedProps = {
662
+ ...reference,
663
+ specifier: url,
664
+ url,
665
+ original: reference.original || reference,
666
+ prev: reference,
667
+ };
668
+ return redirectedProps;
669
+ };
670
+
671
+ const applyReferenceEffectsOnUrlInfo = (reference) => {
672
+ const referencedUrlInfo = reference.urlInfo;
673
+
674
+ if (referencedUrlInfo.firstReference) {
675
+ return;
676
+ }
677
+ referencedUrlInfo.firstReference = reference;
678
+ referencedUrlInfo.originalUrl =
679
+ referencedUrlInfo.originalUrl || reference.url;
680
+
681
+ if (reference.isEntryPoint || isWebWorkerEntryPointReference(reference)) {
682
+ referencedUrlInfo.isEntryPoint = true;
683
+ }
684
+ Object.assign(referencedUrlInfo.data, reference.data);
685
+ Object.assign(referencedUrlInfo.timing, reference.timing);
686
+ if (reference.injected) {
687
+ referencedUrlInfo.injected = true;
688
+ }
689
+ if (reference.filename && !referencedUrlInfo.filename) {
690
+ referencedUrlInfo.filename = reference.filename;
691
+ }
692
+ if (reference.isInline) {
693
+ referencedUrlInfo.isInline = true;
694
+ referencedUrlInfo.inlineUrlSite = {
695
+ url: reference.ownerUrlInfo.url,
696
+ content: reference.isOriginalPosition
697
+ ? reference.ownerUrlInfo.originalContent
698
+ : reference.ownerUrlInfo.content,
699
+ line: reference.specifierLine,
700
+ column: reference.specifierColumn,
701
+ };
702
+ }
703
+
704
+ if (reference.debug) {
705
+ referencedUrlInfo.debug = true;
706
+ }
707
+ if (reference.expectedType) {
708
+ referencedUrlInfo.typeHint = reference.expectedType;
709
+ }
710
+ if (reference.expectedSubtype) {
711
+ referencedUrlInfo.subtypeHint = reference.expectedSubtype;
712
+ }
713
+ };
@@ -14,8 +14,8 @@ export const sortByDependencies = (nodes) => {
14
14
  }
15
15
  } else {
16
16
  visited.push(url);
17
- nodes[url].dependencies.forEach((dependencyUrl) => {
18
- visit(dependencyUrl, url);
17
+ nodes[url].referenceToOthersSet.forEach((referenceToOther) => {
18
+ visit(referenceToOther.url, url);
19
19
  });
20
20
  sorted.push(url);
21
21
  }