@jsenv/core 37.1.5 → 38.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.
- package/dist/js/autoreload.js +2 -2
- package/dist/jsenv_core.js +3221 -2483
- package/package.json +14 -13
- package/src/build/build.js +246 -1028
- package/src/build/build_specifier_manager.js +1200 -0
- package/src/build/build_urls_generator.js +40 -18
- package/src/build/version_mappings_injection.js +14 -16
- package/src/dev/file_service.js +0 -10
- package/src/dev/start_dev_server.js +0 -2
- package/src/kitchen/kitchen.js +54 -37
- package/src/kitchen/url_graph/references.js +84 -93
- package/src/kitchen/url_graph/url_graph.js +16 -6
- package/src/kitchen/url_graph/url_info_transformations.js +124 -55
- package/src/plugins/autoreload/client/autoreload.js +6 -2
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +20 -16
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +1 -1
- package/src/plugins/cache_control/jsenv_plugin_cache_control.js +2 -2
- package/src/plugins/clean_html/jsenv_plugin_clean_html.js +16 -0
- package/src/plugins/importmap/jsenv_plugin_importmap.js +11 -23
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +16 -1
- package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +14 -24
- package/src/plugins/plugin_controller.js +37 -25
- package/src/plugins/plugins.js +2 -0
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +31 -16
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +12 -6
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +33 -54
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +2 -9
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +15 -8
- package/src/build/build_versions_manager.js +0 -492
|
@@ -1,25 +1,48 @@
|
|
|
1
1
|
import { urlToFilename, urlToRelativeUrl } from "@jsenv/urls";
|
|
2
|
-
import {
|
|
2
|
+
import { ANSI } from "@jsenv/log";
|
|
3
3
|
|
|
4
4
|
export const createBuildUrlsGenerator = ({
|
|
5
|
+
logger,
|
|
6
|
+
sourceDirectoryUrl,
|
|
5
7
|
buildDirectoryUrl,
|
|
6
8
|
assetsDirectory,
|
|
7
9
|
}) => {
|
|
8
10
|
const cache = {};
|
|
9
|
-
|
|
10
11
|
const getUrlName = (url, urlInfo) => {
|
|
11
12
|
if (!urlInfo) {
|
|
12
13
|
return urlToFilename(url);
|
|
13
14
|
}
|
|
14
|
-
if (urlInfo.
|
|
15
|
-
return urlInfo.
|
|
15
|
+
if (urlInfo.filenameHint) {
|
|
16
|
+
return urlInfo.filenameHint;
|
|
16
17
|
}
|
|
17
18
|
return urlToFilename(url);
|
|
18
19
|
};
|
|
19
20
|
|
|
20
|
-
const
|
|
21
|
+
const buildUrlCache = new Map();
|
|
22
|
+
|
|
23
|
+
const associateBuildUrl = (url, buildUrl) => {
|
|
24
|
+
buildUrlCache.set(url, buildUrl);
|
|
25
|
+
logger.debug(`associate a build url
|
|
26
|
+
${ANSI.color(url, ANSI.GREY)} ->
|
|
27
|
+
${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
28
|
+
`);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const generate = (url, { urlInfo, ownerUrlInfo }) => {
|
|
32
|
+
const buildUrlFromCache = buildUrlCache.get(url);
|
|
33
|
+
if (buildUrlFromCache) {
|
|
34
|
+
return buildUrlFromCache;
|
|
35
|
+
}
|
|
36
|
+
if (urlInfo.type === "directory") {
|
|
37
|
+
const directoryPath = urlToRelativeUrl(url, sourceDirectoryUrl);
|
|
38
|
+
const { search } = new URL(url);
|
|
39
|
+
const buildUrl = `${buildDirectoryUrl}${directoryPath}${search}`;
|
|
40
|
+
associateBuildUrl(url, buildUrl);
|
|
41
|
+
return buildUrl;
|
|
42
|
+
}
|
|
43
|
+
|
|
21
44
|
const directoryPath = determineDirectoryPath({
|
|
22
|
-
|
|
45
|
+
sourceDirectoryUrl,
|
|
23
46
|
assetsDirectory,
|
|
24
47
|
urlInfo,
|
|
25
48
|
ownerUrlInfo,
|
|
@@ -45,8 +68,11 @@ export const createBuildUrlsGenerator = ({
|
|
|
45
68
|
integer++;
|
|
46
69
|
nameCandidate = `${basename}${integer}${extension}`;
|
|
47
70
|
}
|
|
48
|
-
|
|
49
|
-
|
|
71
|
+
hash = "";
|
|
72
|
+
const buildUrl = `${buildDirectoryUrl}${directoryPath}${nameCandidate}${search}${hash}`;
|
|
73
|
+
associateBuildUrl(url, buildUrl);
|
|
74
|
+
return buildUrl;
|
|
75
|
+
};
|
|
50
76
|
|
|
51
77
|
return {
|
|
52
78
|
generate,
|
|
@@ -74,26 +100,22 @@ const splitFileExtension = (filename) => {
|
|
|
74
100
|
};
|
|
75
101
|
|
|
76
102
|
const determineDirectoryPath = ({
|
|
77
|
-
|
|
103
|
+
sourceDirectoryUrl,
|
|
78
104
|
assetsDirectory,
|
|
79
105
|
urlInfo,
|
|
80
106
|
ownerUrlInfo,
|
|
81
107
|
}) => {
|
|
108
|
+
if (urlInfo.dirnameHint) {
|
|
109
|
+
return urlInfo.dirnameHint;
|
|
110
|
+
}
|
|
82
111
|
if (urlInfo.type === "directory") {
|
|
83
112
|
return "";
|
|
84
113
|
}
|
|
85
|
-
if (ownerUrlInfo && ownerUrlInfo.type === "directory") {
|
|
86
|
-
const ownerDirectoryPath = urlToRelativeUrl(
|
|
87
|
-
ownerUrlInfo.url,
|
|
88
|
-
buildDirectoryUrl,
|
|
89
|
-
);
|
|
90
|
-
return ownerDirectoryPath;
|
|
91
|
-
}
|
|
92
114
|
if (urlInfo.isInline) {
|
|
93
115
|
const parentDirectoryPath = determineDirectoryPath({
|
|
94
|
-
|
|
116
|
+
sourceDirectoryUrl,
|
|
95
117
|
assetsDirectory,
|
|
96
|
-
urlInfo: ownerUrlInfo,
|
|
118
|
+
urlInfo: ownerUrlInfo || urlInfo.firstReference.ownerUrlInfo,
|
|
97
119
|
});
|
|
98
120
|
return parentDirectoryPath;
|
|
99
121
|
}
|
|
@@ -15,27 +15,25 @@ export const injectVersionMappingsAsGlobal = async (
|
|
|
15
15
|
versionMappings,
|
|
16
16
|
) => {
|
|
17
17
|
if (urlInfo.type === "html") {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
),
|
|
25
|
-
}),
|
|
18
|
+
const minification = Boolean(
|
|
19
|
+
urlInfo.context.getPluginMeta("willMinifyJsClassic"),
|
|
20
|
+
);
|
|
21
|
+
const content = generateClientCodeForVersionMappings(versionMappings, {
|
|
22
|
+
globalName: "window",
|
|
23
|
+
minification,
|
|
26
24
|
});
|
|
25
|
+
await prependContent(urlInfo, { type: "js_classic", content });
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
28
|
if (urlInfo.type === "js_classic" || urlInfo.type === "js_module") {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
),
|
|
37
|
-
}),
|
|
29
|
+
const minification = Boolean(
|
|
30
|
+
urlInfo.context.getPluginMeta("willMinifyJsClassic"),
|
|
31
|
+
);
|
|
32
|
+
const content = generateClientCodeForVersionMappings(versionMappings, {
|
|
33
|
+
globalName: isWebWorkerUrlInfo(urlInfo) ? "self" : "window",
|
|
34
|
+
minification,
|
|
38
35
|
});
|
|
36
|
+
await prependContent(urlInfo, { type: "js_classic", content });
|
|
39
37
|
return;
|
|
40
38
|
}
|
|
41
39
|
};
|
package/src/dev/file_service.js
CHANGED
|
@@ -2,7 +2,6 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { serveDirectory, composeTwoResponses } from "@jsenv/server";
|
|
3
3
|
import { bufferToEtag } from "@jsenv/filesystem";
|
|
4
4
|
import { URL_META } from "@jsenv/url-meta";
|
|
5
|
-
import { RUNTIME_COMPAT } from "@jsenv/runtime-compat";
|
|
6
5
|
|
|
7
6
|
import { WEB_URL_CONVERTER } from "../helpers/web_url_converter.js";
|
|
8
7
|
import { watchSourceFiles } from "../helpers/watch_source_files.js";
|
|
@@ -37,7 +36,6 @@ export const createFileService = ({
|
|
|
37
36
|
cacheControl,
|
|
38
37
|
ribbon,
|
|
39
38
|
sourcemaps,
|
|
40
|
-
sourcemapsSourcesProtocol,
|
|
41
39
|
sourcemapsSourcesContent,
|
|
42
40
|
outDirectoryUrl,
|
|
43
41
|
}) => {
|
|
@@ -103,13 +101,6 @@ export const createFileService = ({
|
|
|
103
101
|
dev: true,
|
|
104
102
|
runtimeCompat,
|
|
105
103
|
clientRuntimeCompat,
|
|
106
|
-
systemJsTranspilation:
|
|
107
|
-
!RUNTIME_COMPAT.isSupported(
|
|
108
|
-
clientRuntimeCompat,
|
|
109
|
-
"script_type_module",
|
|
110
|
-
) ||
|
|
111
|
-
!RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_dynamic") ||
|
|
112
|
-
!RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_meta"),
|
|
113
104
|
plugins: [
|
|
114
105
|
...plugins,
|
|
115
106
|
...getCorePlugins({
|
|
@@ -131,7 +122,6 @@ export const createFileService = ({
|
|
|
131
122
|
supervisor,
|
|
132
123
|
minification: false,
|
|
133
124
|
sourcemaps,
|
|
134
|
-
sourcemapsSourcesProtocol,
|
|
135
125
|
sourcemapsSourcesContent,
|
|
136
126
|
outDirectoryUrl: outDirectoryUrl
|
|
137
127
|
? new URL(`${runtimeName}@${runtimeVersion}/`, outDirectoryUrl)
|
|
@@ -62,7 +62,6 @@ export const startDevServer = async ({
|
|
|
62
62
|
onKitchenCreated = () => {},
|
|
63
63
|
|
|
64
64
|
sourcemaps = "inline",
|
|
65
|
-
sourcemapsSourcesProtocol,
|
|
66
65
|
sourcemapsSourcesContent,
|
|
67
66
|
outDirectoryUrl,
|
|
68
67
|
...rest
|
|
@@ -203,7 +202,6 @@ export const startDevServer = async ({
|
|
|
203
202
|
cacheControl,
|
|
204
203
|
ribbon,
|
|
205
204
|
sourcemaps,
|
|
206
|
-
sourcemapsSourcesProtocol,
|
|
207
205
|
sourcemapsSourcesContent,
|
|
208
206
|
outDirectoryUrl,
|
|
209
207
|
}),
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -39,7 +39,6 @@ export const createKitchen = ({
|
|
|
39
39
|
supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
|
|
40
40
|
dev = false,
|
|
41
41
|
build = false,
|
|
42
|
-
shape = false,
|
|
43
42
|
runtimeCompat,
|
|
44
43
|
// during dev/test clientRuntimeCompat is a single runtime
|
|
45
44
|
// during build clientRuntimeCompat is runtimeCompat
|
|
@@ -47,16 +46,18 @@ export const createKitchen = ({
|
|
|
47
46
|
plugins,
|
|
48
47
|
supervisor,
|
|
49
48
|
sourcemaps = dev ? "inline" : "none", // "programmatic" and "file" also allowed
|
|
49
|
+
sourcemapsComment,
|
|
50
|
+
sourcemapsSources,
|
|
50
51
|
sourcemapsSourcesProtocol,
|
|
51
52
|
sourcemapsSourcesContent,
|
|
52
|
-
sourcemapsSourcesRelative,
|
|
53
53
|
outDirectoryUrl,
|
|
54
|
-
|
|
54
|
+
initialContext = {},
|
|
55
|
+
initialPluginsMeta = {},
|
|
55
56
|
}) => {
|
|
56
57
|
const logger = createLogger({ logLevel });
|
|
57
58
|
const kitchen = {
|
|
58
59
|
context: {
|
|
59
|
-
...
|
|
60
|
+
...initialContext,
|
|
60
61
|
kitchen: null,
|
|
61
62
|
signal,
|
|
62
63
|
logger,
|
|
@@ -64,7 +65,6 @@ export const createKitchen = ({
|
|
|
64
65
|
mainFilePath,
|
|
65
66
|
dev,
|
|
66
67
|
build,
|
|
67
|
-
shape,
|
|
68
68
|
runtimeCompat,
|
|
69
69
|
clientRuntimeCompat,
|
|
70
70
|
inlineContentClientFileUrl,
|
|
@@ -88,11 +88,11 @@ export const createKitchen = ({
|
|
|
88
88
|
});
|
|
89
89
|
kitchen.graph = graph;
|
|
90
90
|
|
|
91
|
-
const pluginController = createPluginController(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
pluginController.getPluginMeta,
|
|
91
|
+
const pluginController = createPluginController(
|
|
92
|
+
kitchenContext,
|
|
93
|
+
initialPluginsMeta,
|
|
95
94
|
);
|
|
95
|
+
kitchen.pluginController = pluginController;
|
|
96
96
|
plugins.forEach((pluginEntry) => {
|
|
97
97
|
pluginController.pushPlugin(pluginEntry);
|
|
98
98
|
});
|
|
@@ -100,9 +100,10 @@ export const createKitchen = ({
|
|
|
100
100
|
const urlInfoTransformer = createUrlInfoTransformer({
|
|
101
101
|
logger,
|
|
102
102
|
sourcemaps,
|
|
103
|
+
sourcemapsComment,
|
|
104
|
+
sourcemapsSources,
|
|
103
105
|
sourcemapsSourcesProtocol,
|
|
104
106
|
sourcemapsSourcesContent,
|
|
105
|
-
sourcemapsSourcesRelative,
|
|
106
107
|
outDirectoryUrl,
|
|
107
108
|
supervisor,
|
|
108
109
|
});
|
|
@@ -229,6 +230,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
229
230
|
);
|
|
230
231
|
}
|
|
231
232
|
reference.generatedUrl = reference.url;
|
|
233
|
+
reference.generatedSearchParams = reference.searchParams;
|
|
232
234
|
return reference;
|
|
233
235
|
} catch (error) {
|
|
234
236
|
throw createResolveUrlError({
|
|
@@ -255,19 +257,33 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
255
257
|
// - convey information (?hot)
|
|
256
258
|
// But do not represent an other resource, it is considered as
|
|
257
259
|
// the same resource under the hood
|
|
260
|
+
const searchParamTransformationMap = new Map();
|
|
258
261
|
pluginController.callHooks(
|
|
259
262
|
"transformReferenceSearchParams",
|
|
260
263
|
reference,
|
|
261
264
|
(returnValue) => {
|
|
262
265
|
Object.keys(returnValue).forEach((key) => {
|
|
263
|
-
|
|
266
|
+
searchParamTransformationMap.set(key, returnValue[key]);
|
|
264
267
|
});
|
|
265
|
-
const referencedUrlObject = new URL(reference.url);
|
|
266
|
-
const search = reference.searchParams.toString();
|
|
267
|
-
referencedUrlObject.search = search;
|
|
268
|
-
reference.generatedUrl = normalizeUrl(referencedUrlObject.href);
|
|
269
268
|
},
|
|
270
269
|
);
|
|
270
|
+
if (searchParamTransformationMap.size) {
|
|
271
|
+
const generatedSearchParams = new URLSearchParams(
|
|
272
|
+
reference.searchParams,
|
|
273
|
+
);
|
|
274
|
+
searchParamTransformationMap.forEach((value, key) => {
|
|
275
|
+
if (value === undefined) {
|
|
276
|
+
generatedSearchParams.delete(key);
|
|
277
|
+
} else {
|
|
278
|
+
generatedSearchParams.set(key, value);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
const generatedUrlObject = new URL(reference.url);
|
|
282
|
+
const generatedSearch = generatedSearchParams.toString();
|
|
283
|
+
generatedUrlObject.search = generatedSearch;
|
|
284
|
+
reference.generatedUrl = normalizeUrl(generatedUrlObject.href);
|
|
285
|
+
reference.generatedSearchParams = generatedSearchParams;
|
|
286
|
+
}
|
|
271
287
|
}
|
|
272
288
|
format: {
|
|
273
289
|
const returnValue = pluginController.callHooksUntil(
|
|
@@ -313,7 +329,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
313
329
|
subtype,
|
|
314
330
|
originalUrl,
|
|
315
331
|
sourcemap,
|
|
316
|
-
filename,
|
|
317
332
|
|
|
318
333
|
status = 200,
|
|
319
334
|
headers = {},
|
|
@@ -348,9 +363,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
348
363
|
if (typeof isEntryPoint === "boolean") {
|
|
349
364
|
urlInfo.isEntryPoint = isEntryPoint;
|
|
350
365
|
}
|
|
351
|
-
if (filename && !urlInfo.filename) {
|
|
352
|
-
urlInfo.filename = filename;
|
|
353
|
-
}
|
|
354
366
|
assertFetchedContentCompliance({
|
|
355
367
|
urlInfo,
|
|
356
368
|
content,
|
|
@@ -468,16 +480,17 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
468
480
|
if (e.code === "DIRECTORY_REFERENCE_NOT_ALLOWED") {
|
|
469
481
|
throw e;
|
|
470
482
|
}
|
|
471
|
-
if (urlInfo.isInline) {
|
|
483
|
+
if (urlInfo.isInline && errorOnInlineContentCanSkipThrow(urlInfo)) {
|
|
472
484
|
// When something like <style> or <script> contains syntax error
|
|
473
485
|
// the HTML in itself it still valid
|
|
474
486
|
// keep the syntax error and continue with the HTML
|
|
475
487
|
const errorInfo =
|
|
476
488
|
e.code === "PARSE_ERROR"
|
|
477
489
|
? `${e.cause.reasonCode}\n${e.traceMessage}`
|
|
478
|
-
:
|
|
490
|
+
: e.stack;
|
|
479
491
|
logger.error(
|
|
480
|
-
`Error while handling ${urlInfo.type} declared in ${urlInfo.firstReference.trace.message}:
|
|
492
|
+
`Error while handling ${urlInfo.type} declared in ${urlInfo.firstReference.trace.message}:
|
|
493
|
+
${errorInfo}`,
|
|
481
494
|
);
|
|
482
495
|
} else {
|
|
483
496
|
throw e;
|
|
@@ -571,6 +584,23 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
571
584
|
return kitchen;
|
|
572
585
|
};
|
|
573
586
|
|
|
587
|
+
// if we are cooking the inline content internally it's better not to throw
|
|
588
|
+
// because the main url info (html) is still valid
|
|
589
|
+
// but if we are explicitely requesting inline content during dev
|
|
590
|
+
// then we should throw
|
|
591
|
+
const errorOnInlineContentCanSkipThrow = (urlInfo) => {
|
|
592
|
+
if (urlInfo.context.build) {
|
|
593
|
+
return true;
|
|
594
|
+
}
|
|
595
|
+
if (
|
|
596
|
+
urlInfo.context.reference &&
|
|
597
|
+
urlInfo.context.reference.url === urlInfo.url
|
|
598
|
+
) {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
return true;
|
|
602
|
+
};
|
|
603
|
+
|
|
574
604
|
const debounceCook = (cook) => {
|
|
575
605
|
const pendingDishes = new Map();
|
|
576
606
|
return async (urlInfo, context) => {
|
|
@@ -619,19 +649,6 @@ const memoizeCook = (cook) => {
|
|
|
619
649
|
};
|
|
620
650
|
};
|
|
621
651
|
|
|
622
|
-
const memoizeGetPluginMeta = (getPluginMeta) => {
|
|
623
|
-
const cache = new Map();
|
|
624
|
-
return (id) => {
|
|
625
|
-
const fromCache = cache.get(id);
|
|
626
|
-
if (fromCache) {
|
|
627
|
-
return fromCache;
|
|
628
|
-
}
|
|
629
|
-
const value = getPluginMeta(id);
|
|
630
|
-
cache.set(id, value);
|
|
631
|
-
return value;
|
|
632
|
-
};
|
|
633
|
-
};
|
|
634
|
-
|
|
635
652
|
const memoizeIsSupported = (runtimeCompat) => {
|
|
636
653
|
const cache = new Map();
|
|
637
654
|
return (feature, featureCompat) => {
|
|
@@ -697,8 +714,8 @@ const determineFileUrlForOutDirectory = (urlInfo) => {
|
|
|
697
714
|
fsRootUrl.length,
|
|
698
715
|
)}`;
|
|
699
716
|
}
|
|
700
|
-
if (urlInfo.
|
|
701
|
-
url = setUrlFilename(url, urlInfo.
|
|
717
|
+
if (urlInfo.filenameHint) {
|
|
718
|
+
url = setUrlFilename(url, urlInfo.filenameHint);
|
|
702
719
|
}
|
|
703
720
|
return moveUrl({
|
|
704
721
|
url,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCallerPosition,
|
|
3
3
|
stringifyUrlSite,
|
|
4
|
-
generateInlineContentUrl,
|
|
5
4
|
urlToBasename,
|
|
6
5
|
urlToExtension,
|
|
7
6
|
} from "@jsenv/urls";
|
|
7
|
+
import { generateUrlForInlineContent } from "@jsenv/ast";
|
|
8
8
|
|
|
9
9
|
import { isWebWorkerEntryPointReference } from "../web_workers.js";
|
|
10
10
|
import { prependContent } from "../prepend_content.js";
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
let referenceId = 0;
|
|
12
13
|
|
|
13
14
|
export const createDependencies = (ownerUrlInfo) => {
|
|
14
15
|
const { referenceToOthersSet } = ownerUrlInfo;
|
|
@@ -101,37 +102,10 @@ export const createDependencies = (ownerUrlInfo) => {
|
|
|
101
102
|
specifier: sideEffectFileUrl,
|
|
102
103
|
...rest,
|
|
103
104
|
});
|
|
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
105
|
|
|
132
106
|
const injectAsBannerCodeBeforeFinalize = (urlInfoReceiver) => {
|
|
133
107
|
const basename = urlToBasename(sideEffectFileUrl);
|
|
134
|
-
const inlineUrl =
|
|
108
|
+
const inlineUrl = generateUrlForInlineContent({
|
|
135
109
|
url: urlInfoReceiver.url,
|
|
136
110
|
basename,
|
|
137
111
|
extension: urlToExtension(sideEffectFileUrl),
|
|
@@ -158,59 +132,69 @@ export const createDependencies = (ownerUrlInfo) => {
|
|
|
158
132
|
// during dev cooking files is incremental
|
|
159
133
|
// so HTML/JS is already executed by the browser
|
|
160
134
|
// 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
135
|
// During build:
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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;
|
|
136
|
+
// files are not executed so it's possible to inject reference
|
|
137
|
+
// when discovering a side effect file
|
|
138
|
+
const visitedMap = new Map();
|
|
139
|
+
let foundOrInjectedOnce = false;
|
|
140
|
+
const visit = (urlInfo) => {
|
|
141
|
+
urlInfo = urlInfo.findParentIfInline() || urlInfo;
|
|
142
|
+
const value = visitedMap.get(urlInfo);
|
|
143
|
+
if (value !== undefined) {
|
|
144
|
+
return value;
|
|
199
145
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
146
|
+
|
|
147
|
+
// search if already referenced
|
|
148
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
149
|
+
if (referenceToOther === sideEffectFileReference) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (referenceToOther.url === sideEffectFileUrl) {
|
|
153
|
+
// consider this reference becomes the last reference
|
|
154
|
+
// this ensure this ref is properly detected as inlined by urlInfo.isUsed()
|
|
155
|
+
sideEffectFileReference.next =
|
|
156
|
+
referenceToOther.next || referenceToOther;
|
|
157
|
+
foundOrInjectedOnce = true;
|
|
158
|
+
visitedMap.set(urlInfo, true);
|
|
204
159
|
return true;
|
|
205
160
|
}
|
|
206
|
-
if (
|
|
161
|
+
if (
|
|
162
|
+
referenceToOther.original &&
|
|
163
|
+
referenceToOther.original.url === sideEffectFileUrl
|
|
164
|
+
) {
|
|
165
|
+
// consider this reference becomes the last reference
|
|
166
|
+
// this ensure this ref is properly detected as inlined by urlInfo.isUsed()
|
|
167
|
+
sideEffectFileReference.next =
|
|
168
|
+
referenceToOther.next || referenceToOther;
|
|
169
|
+
foundOrInjectedOnce = true;
|
|
170
|
+
visitedMap.set(urlInfo, true);
|
|
207
171
|
return true;
|
|
208
172
|
}
|
|
209
|
-
return false;
|
|
210
|
-
});
|
|
211
|
-
if (!found) {
|
|
212
|
-
injectAsBannerCodeBeforeFinalize(entryPointUrlInfo);
|
|
213
173
|
}
|
|
174
|
+
// not referenced and we reach an entry point, stop there
|
|
175
|
+
if (urlInfo.isEntryPoint) {
|
|
176
|
+
foundOrInjectedOnce = true;
|
|
177
|
+
visitedMap.set(urlInfo, true);
|
|
178
|
+
injectAsBannerCodeBeforeFinalize(urlInfo);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
visitedMap.set(urlInfo, false);
|
|
182
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
183
|
+
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
184
|
+
visit(urlInfoReferencingThisOne);
|
|
185
|
+
// during dev the first urlInfo where we inject the side effect file is enough
|
|
186
|
+
// during build we want to inject into every possible entry point
|
|
187
|
+
if (foundOrInjectedOnce && urlInfo.context.dev) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
};
|
|
193
|
+
visit(ownerUrlInfo);
|
|
194
|
+
if (ownerUrlInfo.context.dev && !foundOrInjectedOnce) {
|
|
195
|
+
injectAsBannerCodeBeforeFinalize(
|
|
196
|
+
ownerUrlInfo.findParentIfInline() || ownerUrlInfo,
|
|
197
|
+
);
|
|
214
198
|
}
|
|
215
199
|
};
|
|
216
200
|
|
|
@@ -275,7 +259,7 @@ const createReference = ({
|
|
|
275
259
|
expectedContentType,
|
|
276
260
|
expectedType,
|
|
277
261
|
expectedSubtype,
|
|
278
|
-
|
|
262
|
+
filenameHint,
|
|
279
263
|
integrity,
|
|
280
264
|
crossorigin,
|
|
281
265
|
specifier,
|
|
@@ -326,6 +310,7 @@ const createReference = ({
|
|
|
326
310
|
}
|
|
327
311
|
}
|
|
328
312
|
const reference = {
|
|
313
|
+
id: ++referenceId,
|
|
329
314
|
ownerUrlInfo,
|
|
330
315
|
original,
|
|
331
316
|
prev,
|
|
@@ -342,7 +327,7 @@ const createReference = ({
|
|
|
342
327
|
expectedContentType,
|
|
343
328
|
expectedType,
|
|
344
329
|
expectedSubtype,
|
|
345
|
-
|
|
330
|
+
filenameHint,
|
|
346
331
|
integrity,
|
|
347
332
|
crossorigin,
|
|
348
333
|
specifier,
|
|
@@ -445,6 +430,7 @@ const createReference = ({
|
|
|
445
430
|
original: reference.original || reference,
|
|
446
431
|
prev: reference,
|
|
447
432
|
trace,
|
|
433
|
+
injected: reference.injected,
|
|
448
434
|
expectedType: reference.expectedType,
|
|
449
435
|
...props,
|
|
450
436
|
});
|
|
@@ -625,6 +611,8 @@ const applyDependencyRemovalEffects = (reference) => {
|
|
|
625
611
|
}
|
|
626
612
|
return false;
|
|
627
613
|
}
|
|
614
|
+
// referencedUrlInfo.firstReference = null;
|
|
615
|
+
// referencedUrlInfo.lastReference = null;
|
|
628
616
|
referencedUrlInfo.onDereferenced(reference);
|
|
629
617
|
return true;
|
|
630
618
|
};
|
|
@@ -691,8 +679,23 @@ const getRedirectedReferenceProps = (reference, url) => {
|
|
|
691
679
|
|
|
692
680
|
const applyReferenceEffectsOnUrlInfo = (reference) => {
|
|
693
681
|
const referencedUrlInfo = reference.urlInfo;
|
|
682
|
+
referencedUrlInfo.lastReference = reference;
|
|
683
|
+
if (reference.isInline) {
|
|
684
|
+
referencedUrlInfo.isInline = true;
|
|
685
|
+
referencedUrlInfo.inlineUrlSite = {
|
|
686
|
+
url: reference.ownerUrlInfo.url,
|
|
687
|
+
content: reference.isOriginalPosition
|
|
688
|
+
? reference.ownerUrlInfo.originalContent
|
|
689
|
+
: reference.ownerUrlInfo.content,
|
|
690
|
+
line: reference.specifierLine,
|
|
691
|
+
column: reference.specifierColumn,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
694
|
|
|
695
|
-
if (
|
|
695
|
+
if (
|
|
696
|
+
referencedUrlInfo.firstReference &&
|
|
697
|
+
!referencedUrlInfo.firstReference.isWeak
|
|
698
|
+
) {
|
|
696
699
|
return;
|
|
697
700
|
}
|
|
698
701
|
referencedUrlInfo.firstReference = reference;
|
|
@@ -707,21 +710,9 @@ const applyReferenceEffectsOnUrlInfo = (reference) => {
|
|
|
707
710
|
if (reference.injected) {
|
|
708
711
|
referencedUrlInfo.injected = true;
|
|
709
712
|
}
|
|
710
|
-
if (reference.
|
|
711
|
-
referencedUrlInfo.
|
|
713
|
+
if (reference.filenameHint && !referencedUrlInfo.filenameHint) {
|
|
714
|
+
referencedUrlInfo.filenameHint = reference.filenameHint;
|
|
712
715
|
}
|
|
713
|
-
if (reference.isInline) {
|
|
714
|
-
referencedUrlInfo.isInline = true;
|
|
715
|
-
referencedUrlInfo.inlineUrlSite = {
|
|
716
|
-
url: reference.ownerUrlInfo.url,
|
|
717
|
-
content: reference.isOriginalPosition
|
|
718
|
-
? reference.ownerUrlInfo.originalContent
|
|
719
|
-
: reference.ownerUrlInfo.content,
|
|
720
|
-
line: reference.specifierLine,
|
|
721
|
-
column: reference.specifierColumn,
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
|
|
725
716
|
if (reference.debug) {
|
|
726
717
|
referencedUrlInfo.debug = true;
|
|
727
718
|
}
|