@jsenv/core 36.3.0 → 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.
- package/dist/js/autoreload.js +6 -5
- package/dist/js/import_meta_hot.js +4 -4
- package/dist/js/server_events_client.js +422 -304
- package/dist/jsenv_core.js +3819 -3256
- package/package.json +18 -17
- package/src/build/build.js +342 -658
- package/src/build/build_urls_generator.js +8 -8
- package/src/build/build_versions_manager.js +495 -0
- package/src/build/version_mappings_injection.js +27 -16
- package/src/dev/file_service.js +80 -91
- package/src/dev/start_dev_server.js +5 -3
- package/src/kitchen/errors.js +16 -16
- package/src/kitchen/fetched_content_compliance.js +4 -8
- package/src/kitchen/kitchen.js +367 -939
- package/src/kitchen/prepend_content.js +13 -35
- package/src/kitchen/url_graph/references.js +713 -0
- package/src/kitchen/url_graph/sort_by_dependencies.js +2 -2
- package/src/kitchen/url_graph/url_content.js +96 -0
- package/src/kitchen/url_graph/url_graph.js +439 -0
- package/src/kitchen/url_graph/url_graph_report.js +6 -4
- package/src/kitchen/url_graph/url_graph_visitor.js +14 -12
- package/src/kitchen/url_graph/url_info_transformations.js +180 -184
- package/src/plugins/autoreload/client/autoreload.js +1 -0
- package/src/plugins/autoreload/client/reload.js +6 -6
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +2 -2
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +2 -2
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +84 -78
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +52 -0
- package/src/plugins/cache_control/jsenv_plugin_cache_control.js +1 -1
- package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +2 -2
- package/src/plugins/global_scenarios/jsenv_plugin_global_scenarios.js +3 -3
- package/src/plugins/import_meta_hot/client/import_meta_hot.js +4 -4
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +18 -20
- package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +35 -37
- package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -17
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +70 -50
- package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +72 -54
- package/src/plugins/plugin_controller.js +92 -27
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +18 -20
- package/src/plugins/reference_analysis/css/jsenv_plugin_css_reference_analysis.js +4 -5
- package/src/plugins/reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js +18 -16
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +13 -20
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +55 -72
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +33 -42
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +16 -7
- package/src/plugins/reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js +4 -3
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +16 -6
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +30 -24
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +8 -5
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +3 -3
- package/src/plugins/server_events/client/server_events_client.js +460 -15
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +13 -29
- package/src/plugins/version_search_param/jsenv_plugin_version_search_param.js +1 -1
- package/src/build/version_generator.js +0 -19
- package/src/kitchen/url_graph/url_graph_loader.js +0 -77
- package/src/kitchen/url_graph.js +0 -322
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +0 -42
- package/src/plugins/resolution_node_esm/url_type_from_reference.js +0 -13
- package/src/plugins/server_events/client/connection_manager.js +0 -170
- package/src/plugins/server_events/client/event_source_connection.js +0 -83
- package/src/plugins/server_events/client/events_manager.js +0 -75
- package/src/plugins/server_events/client/web_socket_connection.js +0 -81
- /package/src/kitchen/{url_specifier_encoding.js → url_graph/url_specifier_encoding.js} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { parseJsWithAcorn } from "@jsenv/ast";
|
|
2
|
+
import { bufferToEtag } from "@jsenv/filesystem";
|
|
3
|
+
|
|
4
|
+
export const defineGettersOnPropertiesDerivedFromOriginalContent = (
|
|
5
|
+
urlInfo,
|
|
6
|
+
) => {
|
|
7
|
+
const originalContentAstDescriptor = Object.getOwnPropertyDescriptor(
|
|
8
|
+
urlInfo,
|
|
9
|
+
"originalContentAst",
|
|
10
|
+
);
|
|
11
|
+
if (originalContentAstDescriptor.value === undefined) {
|
|
12
|
+
defineVolatileGetter(urlInfo, "originalContentAst", () => {
|
|
13
|
+
return getContentAst(urlInfo.originalContent, urlInfo.type, urlInfo.url);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
const originalContentEtagDescriptor = Object.getOwnPropertyDescriptor(
|
|
17
|
+
urlInfo,
|
|
18
|
+
"originalContentEtag",
|
|
19
|
+
);
|
|
20
|
+
if (originalContentEtagDescriptor.value === undefined) {
|
|
21
|
+
defineVolatileGetter(urlInfo, "originalContentEtag", () => {
|
|
22
|
+
return bufferToEtag(Buffer.from(urlInfo.originalContent));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const defineGettersOnPropertiesDerivedFromContent = (urlInfo) => {
|
|
28
|
+
const contentAstDescriptor = Object.getOwnPropertyDescriptor(
|
|
29
|
+
urlInfo,
|
|
30
|
+
"contentAst",
|
|
31
|
+
);
|
|
32
|
+
if (contentAstDescriptor.value === undefined) {
|
|
33
|
+
defineVolatileGetter(urlInfo, "contentAst", () => {
|
|
34
|
+
if (urlInfo.content === urlInfo.originalContent) {
|
|
35
|
+
return urlInfo.originalContentAst;
|
|
36
|
+
}
|
|
37
|
+
const ast = getContentAst(urlInfo.content, urlInfo.type, urlInfo.url);
|
|
38
|
+
return ast;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const contentEtagDescriptor = Object.getOwnPropertyDescriptor(
|
|
42
|
+
urlInfo,
|
|
43
|
+
"contentEtag",
|
|
44
|
+
);
|
|
45
|
+
if (contentEtagDescriptor.value === undefined) {
|
|
46
|
+
defineVolatileGetter(urlInfo, "contentEtag", () => {
|
|
47
|
+
if (urlInfo.content === urlInfo.originalContent) {
|
|
48
|
+
return urlInfo.originalContentEtag;
|
|
49
|
+
}
|
|
50
|
+
return getContentEtag(urlInfo.content);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const defineVolatileGetter = (object, property, getter) => {
|
|
56
|
+
const restore = (value) => {
|
|
57
|
+
Object.defineProperty(object, property, {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
writable: true,
|
|
61
|
+
value,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(object, property, {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
configurable: true,
|
|
68
|
+
get: () => {
|
|
69
|
+
const value = getter();
|
|
70
|
+
restore(value);
|
|
71
|
+
return value;
|
|
72
|
+
},
|
|
73
|
+
set: restore,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const getContentAst = (content, type, url) => {
|
|
78
|
+
if (type === "js_module") {
|
|
79
|
+
return parseJsWithAcorn({
|
|
80
|
+
js: content,
|
|
81
|
+
url,
|
|
82
|
+
isJsModule: true,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (type === "js_classic") {
|
|
86
|
+
return parseJsWithAcorn({
|
|
87
|
+
js: content,
|
|
88
|
+
url,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const getContentEtag = (content) => {
|
|
95
|
+
return bufferToEtag(Buffer.from(content));
|
|
96
|
+
};
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import {
|
|
2
|
+
urlToRelativeUrl,
|
|
3
|
+
asUrlWithoutSearch,
|
|
4
|
+
injectQueryParamsIntoSpecifier,
|
|
5
|
+
} from "@jsenv/urls";
|
|
6
|
+
|
|
7
|
+
import { urlSpecifierEncoding } from "./url_specifier_encoding.js";
|
|
8
|
+
import { createDependencies } from "./references.js";
|
|
9
|
+
|
|
10
|
+
export const createUrlGraph = ({
|
|
11
|
+
rootDirectoryUrl,
|
|
12
|
+
kitchen,
|
|
13
|
+
name = "anonymous",
|
|
14
|
+
}) => {
|
|
15
|
+
const urlGraph = {};
|
|
16
|
+
const createUrlInfoCallbackRef = { current: () => {} };
|
|
17
|
+
const pruneUrlInfoCallbackRef = { current: () => {} };
|
|
18
|
+
|
|
19
|
+
const urlInfoMap = new Map();
|
|
20
|
+
const hasUrlInfo = (key) => {
|
|
21
|
+
if (typeof key === "string") {
|
|
22
|
+
return urlInfoMap.has(key);
|
|
23
|
+
}
|
|
24
|
+
if (typeof key === "object" && key && key.url) {
|
|
25
|
+
return urlInfoMap.has(key.url);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
};
|
|
29
|
+
const getUrlInfo = (key) => {
|
|
30
|
+
if (typeof key === "string") {
|
|
31
|
+
return urlInfoMap.get(key);
|
|
32
|
+
}
|
|
33
|
+
if (typeof key === "object" && key && key.url) {
|
|
34
|
+
return urlInfoMap.get(key.url);
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
};
|
|
38
|
+
const deleteUrlInfo = (url, lastReferenceFromOther) => {
|
|
39
|
+
const urlInfo = urlInfoMap.get(url);
|
|
40
|
+
if (urlInfo) {
|
|
41
|
+
urlInfo.kitchen.urlInfoTransformer.resetContent(urlInfo);
|
|
42
|
+
urlInfoMap.delete(url);
|
|
43
|
+
urlInfo.modifiedTimestamp = Date.now();
|
|
44
|
+
if (lastReferenceFromOther && !urlInfo.isInline) {
|
|
45
|
+
pruneUrlInfoCallbackRef.current(urlInfo, lastReferenceFromOther);
|
|
46
|
+
}
|
|
47
|
+
urlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
48
|
+
referenceToOther.remove();
|
|
49
|
+
});
|
|
50
|
+
if (urlInfo.searchParams.size > 0) {
|
|
51
|
+
const urlWithoutSearch = asUrlWithoutSearch(urlInfo.url);
|
|
52
|
+
const urlInfoWithoutSearch = getUrlInfo(urlWithoutSearch);
|
|
53
|
+
if (urlInfoWithoutSearch) {
|
|
54
|
+
urlInfoWithoutSearch.searchParamVariantSet.delete(urlInfo);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const addUrlInfo = (urlInfo) => {
|
|
60
|
+
urlInfo.graph = urlGraph;
|
|
61
|
+
urlInfo.kitchen = kitchen;
|
|
62
|
+
urlInfoMap.set(urlInfo.url, urlInfo);
|
|
63
|
+
};
|
|
64
|
+
const reuseOrCreateUrlInfo = (reference, useGeneratedUrl) => {
|
|
65
|
+
const referencedUrl = useGeneratedUrl
|
|
66
|
+
? reference.generatedUrl
|
|
67
|
+
: reference.url;
|
|
68
|
+
const existingUrlInfo = getUrlInfo(referencedUrl);
|
|
69
|
+
if (existingUrlInfo) return existingUrlInfo;
|
|
70
|
+
const ownerUrlInfo = reference.ownerUrlInfo;
|
|
71
|
+
const ownerContext = ownerUrlInfo.context;
|
|
72
|
+
const context = Object.create(ownerContext);
|
|
73
|
+
const referencedUrlInfo = createUrlInfo(referencedUrl, context);
|
|
74
|
+
addUrlInfo(referencedUrlInfo);
|
|
75
|
+
createUrlInfoCallbackRef.current(referencedUrlInfo);
|
|
76
|
+
if (referencedUrlInfo.searchParams.size > 0 && !kitchen.context.shape) {
|
|
77
|
+
// A resource is represented by a url.
|
|
78
|
+
// Variations of a resource are represented by url search params
|
|
79
|
+
// Each representation of the resource is given a dedicated url info
|
|
80
|
+
// object (one url -> one url info)
|
|
81
|
+
// It's because search params often influence the final content returned for that url
|
|
82
|
+
// When a reference contains url search params it must create 2 url infos:
|
|
83
|
+
// 1. The url info corresponding to the url with search params
|
|
84
|
+
// 2. The url info corresponding to url without search params
|
|
85
|
+
// Because the underlying content without search params is used to generate
|
|
86
|
+
// the content modified according to search params
|
|
87
|
+
// This way when a file like "style.css" is considered as modified
|
|
88
|
+
// references like "style.css?as_css_module" are also affected
|
|
89
|
+
const urlWithoutSearch = asUrlWithoutSearch(reference.url);
|
|
90
|
+
// a reference with a search param creates an implicit reference
|
|
91
|
+
// to the file without search param
|
|
92
|
+
const referenceWithoutSearch = reference.addImplicit({
|
|
93
|
+
specifier: urlWithoutSearch,
|
|
94
|
+
url: urlWithoutSearch,
|
|
95
|
+
searchParams: new URLSearchParams(),
|
|
96
|
+
isWeak: true,
|
|
97
|
+
});
|
|
98
|
+
const urlInfoWithoutSearch = referenceWithoutSearch.urlInfo;
|
|
99
|
+
urlInfoWithoutSearch.searchParamVariantSet.add(referencedUrlInfo);
|
|
100
|
+
}
|
|
101
|
+
return referencedUrlInfo;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const inferReference = (specifier, parentUrl) => {
|
|
105
|
+
const parentUrlInfo = getUrlInfo(parentUrl);
|
|
106
|
+
if (!parentUrlInfo) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const seen = [];
|
|
110
|
+
const search = (urlInfo) => {
|
|
111
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
112
|
+
if (urlSpecifierEncoding.decode(referenceToOther) === specifier) {
|
|
113
|
+
return referenceToOther;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const referenceToOther of parentUrlInfo.referenceToOthersSet) {
|
|
117
|
+
if (seen.includes(referenceToOther.url)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
seen.push(referenceToOther.url);
|
|
121
|
+
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
122
|
+
if (referencedUrlInfo.isInline) {
|
|
123
|
+
const firstRef = search(referencedUrlInfo);
|
|
124
|
+
if (firstRef) {
|
|
125
|
+
return firstRef;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
};
|
|
131
|
+
return search(parentUrlInfo);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const getEntryPoints = () => {
|
|
135
|
+
const entryPoints = [];
|
|
136
|
+
urlInfoMap.forEach((urlInfo) => {
|
|
137
|
+
if (urlInfo.isEntryPoint && urlInfo.isUsed()) {
|
|
138
|
+
entryPoints.push(urlInfo);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return entryPoints;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const rootUrlInfo = createUrlInfo(rootDirectoryUrl, kitchen.context);
|
|
145
|
+
rootUrlInfo.isRoot = true;
|
|
146
|
+
addUrlInfo(rootUrlInfo);
|
|
147
|
+
|
|
148
|
+
Object.assign(urlGraph, {
|
|
149
|
+
name,
|
|
150
|
+
rootUrlInfo,
|
|
151
|
+
createUrlInfoCallbackRef,
|
|
152
|
+
pruneUrlInfoCallbackRef,
|
|
153
|
+
|
|
154
|
+
urlInfoMap,
|
|
155
|
+
reuseOrCreateUrlInfo,
|
|
156
|
+
hasUrlInfo,
|
|
157
|
+
getUrlInfo,
|
|
158
|
+
deleteUrlInfo,
|
|
159
|
+
getEntryPoints,
|
|
160
|
+
|
|
161
|
+
inferReference,
|
|
162
|
+
|
|
163
|
+
toObject: () => {
|
|
164
|
+
const data = {};
|
|
165
|
+
urlInfoMap.forEach((urlInfo) => {
|
|
166
|
+
data[urlInfo.url] = urlInfo;
|
|
167
|
+
});
|
|
168
|
+
return data;
|
|
169
|
+
},
|
|
170
|
+
toJSON: (rootDirectoryUrl) => {
|
|
171
|
+
const data = {};
|
|
172
|
+
urlInfoMap.forEach((urlInfo) => {
|
|
173
|
+
if (urlInfo.referenceToOthersSet.size) {
|
|
174
|
+
const relativeUrl = urlToRelativeUrl(urlInfo.url, rootDirectoryUrl);
|
|
175
|
+
const referencedUrlSet = new Set();
|
|
176
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
177
|
+
data[relativeUrl] = referencedUrlSet.add(referenceToOther.url);
|
|
178
|
+
}
|
|
179
|
+
data[relativeUrl] = Array.from(referencedUrlSet).map(
|
|
180
|
+
(referencedUrl) =>
|
|
181
|
+
urlToRelativeUrl(referencedUrl, rootDirectoryUrl),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return data;
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
return urlGraph;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const createUrlInfo = (url, context) => {
|
|
192
|
+
const urlInfo = {
|
|
193
|
+
isRoot: false,
|
|
194
|
+
graph: null,
|
|
195
|
+
kitchen: null,
|
|
196
|
+
context,
|
|
197
|
+
error: null,
|
|
198
|
+
modifiedTimestamp: 0,
|
|
199
|
+
originalContentEtag: null,
|
|
200
|
+
contentEtag: null,
|
|
201
|
+
isWatched: false,
|
|
202
|
+
isValid: () => false,
|
|
203
|
+
data: {}, // plugins can put whatever they want here
|
|
204
|
+
referenceToOthersSet: new Set(),
|
|
205
|
+
referenceFromOthersSet: new Set(),
|
|
206
|
+
firstReference: null, // first reference from an other url to this one
|
|
207
|
+
implicitUrlSet: new Set(),
|
|
208
|
+
searchParamVariantSet: new Set(),
|
|
209
|
+
|
|
210
|
+
type: undefined, // "html", "css", "js_classic", "js_module", "importmap", "sourcemap", "json", "webmanifest", ...
|
|
211
|
+
subtype: undefined, // "worker", "service_worker", "shared_worker" for js, otherwise undefined
|
|
212
|
+
typeHint: undefined,
|
|
213
|
+
subtypeHint: undefined,
|
|
214
|
+
contentType: "", // "text/html", "text/css", "text/javascript", "application/json", ...
|
|
215
|
+
url: null,
|
|
216
|
+
originalUrl: undefined,
|
|
217
|
+
filename: "",
|
|
218
|
+
isEntryPoint: false,
|
|
219
|
+
originalContent: undefined,
|
|
220
|
+
originalContentAst: undefined,
|
|
221
|
+
content: undefined,
|
|
222
|
+
contentAst: undefined,
|
|
223
|
+
contentFinalized: false,
|
|
224
|
+
|
|
225
|
+
sourcemap: null,
|
|
226
|
+
sourcemapIsWrong: false,
|
|
227
|
+
|
|
228
|
+
generatedUrl: null,
|
|
229
|
+
sourcemapGeneratedUrl: null,
|
|
230
|
+
injected: false,
|
|
231
|
+
|
|
232
|
+
isInline: false,
|
|
233
|
+
inlineUrlSite: null,
|
|
234
|
+
jsQuote: null, // maybe move to inlineUrlSite?
|
|
235
|
+
|
|
236
|
+
timing: {},
|
|
237
|
+
headers: {},
|
|
238
|
+
debug: false,
|
|
239
|
+
};
|
|
240
|
+
Object.defineProperty(urlInfo, "url", {
|
|
241
|
+
enumerable: true,
|
|
242
|
+
configurable: false,
|
|
243
|
+
writable: false,
|
|
244
|
+
value: url,
|
|
245
|
+
});
|
|
246
|
+
urlInfo.searchParams = new URL(url).searchParams;
|
|
247
|
+
|
|
248
|
+
urlInfo.dependencies = createDependencies(urlInfo);
|
|
249
|
+
urlInfo.getFirstReferenceFromOther = ({ ignoreWeak } = {}) => {
|
|
250
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
251
|
+
if (referenceFromOther.url === urlInfo.url) {
|
|
252
|
+
if (
|
|
253
|
+
!referenceFromOther.isInline &&
|
|
254
|
+
referenceFromOther.next &&
|
|
255
|
+
referenceFromOther.next.isInline
|
|
256
|
+
) {
|
|
257
|
+
// the url info was inlined, an other reference is required
|
|
258
|
+
// to consider the non-inlined urlInfo as used
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (ignoreWeak && referenceFromOther.isWeak) {
|
|
262
|
+
// weak reference don't count as using the url
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
return referenceFromOther;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
};
|
|
270
|
+
urlInfo.isUsed = () => {
|
|
271
|
+
if (urlInfo.isRoot) {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
// if (urlInfo.type === "sourcemap") {
|
|
275
|
+
// return true;
|
|
276
|
+
// }
|
|
277
|
+
// check if there is a strong reference to this urlInfo
|
|
278
|
+
if (urlInfo.getFirstReferenceFromOther({ ignoreWeak: true })) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
// nothing uses this url anymore
|
|
282
|
+
// - versioning update inline content
|
|
283
|
+
// - file converted for import assertion or js_classic conversion
|
|
284
|
+
// - urlInfo for a file that is now inlined
|
|
285
|
+
return false;
|
|
286
|
+
};
|
|
287
|
+
urlInfo.findParentIfInline = () => {
|
|
288
|
+
let currentUrlInfo = urlInfo;
|
|
289
|
+
const graph = urlInfo.graph;
|
|
290
|
+
while (currentUrlInfo.isInline) {
|
|
291
|
+
const parentUrlInfo = graph.getUrlInfo(currentUrlInfo.inlineUrlSite.url);
|
|
292
|
+
if (!parentUrlInfo.isInline) {
|
|
293
|
+
return parentUrlInfo;
|
|
294
|
+
}
|
|
295
|
+
currentUrlInfo = parentUrlInfo;
|
|
296
|
+
}
|
|
297
|
+
return null;
|
|
298
|
+
};
|
|
299
|
+
urlInfo.isSearchParamVariantOf = (otherUrlInfo) => {
|
|
300
|
+
if (urlInfo.searchParams.size === 0) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
if (otherUrlInfo.searchParams.size > 0) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
const withoutSearch = asUrlWithoutSearch(urlInfo.url);
|
|
307
|
+
if (withoutSearch === otherUrlInfo.url) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
return false;
|
|
311
|
+
};
|
|
312
|
+
urlInfo.getWithoutSearchParam = (searchParam, { expectedType } = {}) => {
|
|
313
|
+
// The search param can be
|
|
314
|
+
// 1. injected by a plugin during "redirectReference"
|
|
315
|
+
// - import assertions
|
|
316
|
+
// - js module fallback to systemjs
|
|
317
|
+
// 2. already inside source files
|
|
318
|
+
// - turn js module into js classic for convenience ?as_js_classic
|
|
319
|
+
// - turn js classic to js module for to make it importable
|
|
320
|
+
if (!urlInfo.searchParams.has(searchParam)) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
const reference = urlInfo.firstReference;
|
|
324
|
+
const newSpecifier = injectQueryParamsIntoSpecifier(reference.specifier, {
|
|
325
|
+
[searchParam]: undefined,
|
|
326
|
+
});
|
|
327
|
+
const referenceWithoutSearchParam = reference.addImplicit({
|
|
328
|
+
type: reference.type,
|
|
329
|
+
subtype: reference.subtype,
|
|
330
|
+
expectedContentType: reference.expectedContentType,
|
|
331
|
+
expectedType: expectedType || reference.expectedType,
|
|
332
|
+
expectedSubtype: reference.expectedSubtype,
|
|
333
|
+
integrity: reference.integrity,
|
|
334
|
+
crossorigin: reference.crossorigin,
|
|
335
|
+
specifierStart: reference.specifierStart,
|
|
336
|
+
specifierEnd: reference.specifierEnd,
|
|
337
|
+
specifierLine: reference.specifierLine,
|
|
338
|
+
specifierColumn: reference.specifierColumn,
|
|
339
|
+
baseUrl: reference.baseUrl,
|
|
340
|
+
isOriginalPosition: reference.isOriginalPosition,
|
|
341
|
+
// ok mais cet ref est implicite + weak
|
|
342
|
+
// donc ne devrait pas etre retournée par getEntryPoints()
|
|
343
|
+
isEntryPoint: reference.isEntryPoint,
|
|
344
|
+
isResourceHint: reference.isResourceHint,
|
|
345
|
+
hasVersioningEffect: reference.hasVersioningEffect,
|
|
346
|
+
version: reference.version,
|
|
347
|
+
content: reference.content,
|
|
348
|
+
contentType: reference.contentType,
|
|
349
|
+
leadsToADirectory: reference.leadsToADirectory,
|
|
350
|
+
debug: reference.debug,
|
|
351
|
+
importAttributes: reference.importAttributes,
|
|
352
|
+
astInfo: reference.astInfo,
|
|
353
|
+
mutation: reference.mutation,
|
|
354
|
+
data: { ...reference.data },
|
|
355
|
+
specifier: newSpecifier,
|
|
356
|
+
isWeak: true,
|
|
357
|
+
isInline: false,
|
|
358
|
+
original: reference.original || reference,
|
|
359
|
+
prev: reference,
|
|
360
|
+
// urlInfo: null,
|
|
361
|
+
// url: null,
|
|
362
|
+
// generatedUrl: null,
|
|
363
|
+
// generatedSpecifier: null,
|
|
364
|
+
// filename: null,
|
|
365
|
+
});
|
|
366
|
+
reference.next = referenceWithoutSearchParam;
|
|
367
|
+
return referenceWithoutSearchParam.urlInfo;
|
|
368
|
+
};
|
|
369
|
+
urlInfo.considerModified = ({ modifiedTimestamp = Date.now() } = {}) => {
|
|
370
|
+
const visitedSet = new Set();
|
|
371
|
+
const iterate = (urlInfo) => {
|
|
372
|
+
if (visitedSet.has(urlInfo)) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
visitedSet.add(urlInfo);
|
|
376
|
+
urlInfo.modifiedTimestamp = modifiedTimestamp;
|
|
377
|
+
urlInfo.kitchen.urlInfoTransformer.resetContent(urlInfo);
|
|
378
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
379
|
+
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
380
|
+
if (referencedUrlInfo.isInline) {
|
|
381
|
+
iterate(referencedUrlInfo);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
for (const searchParamVariant of urlInfo.searchParamVariantSet) {
|
|
385
|
+
iterate(searchParamVariant);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
iterate(urlInfo);
|
|
389
|
+
};
|
|
390
|
+
urlInfo.deleteFromGraph = (reference) => {
|
|
391
|
+
urlInfo.graph.deleteUrlInfo(urlInfo.url, reference);
|
|
392
|
+
};
|
|
393
|
+
urlInfo.cook = (customContext) => {
|
|
394
|
+
return urlInfo.context.cook(urlInfo, customContext);
|
|
395
|
+
};
|
|
396
|
+
urlInfo.cookDependencies = (options) => {
|
|
397
|
+
return urlInfo.context.cookDependencies(urlInfo, options);
|
|
398
|
+
};
|
|
399
|
+
urlInfo.fetchContent = () => {
|
|
400
|
+
return urlInfo.context.fetchUrlContent(urlInfo);
|
|
401
|
+
};
|
|
402
|
+
urlInfo.transformContent = () => {
|
|
403
|
+
return urlInfo.context.transformUrlContent(urlInfo);
|
|
404
|
+
};
|
|
405
|
+
urlInfo.finalizeContent = () => {
|
|
406
|
+
return urlInfo.context.finalizeUrlContent(urlInfo);
|
|
407
|
+
};
|
|
408
|
+
urlInfo.mutateContent = (transformations) => {
|
|
409
|
+
return urlInfo.kitchen.urlInfoTransformer.applyTransformations(
|
|
410
|
+
urlInfo,
|
|
411
|
+
transformations,
|
|
412
|
+
);
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
const contentTransformationCallbackSet = new Set();
|
|
416
|
+
urlInfo.addContentTransformationCallback = (callback) => {
|
|
417
|
+
if (urlInfo.contentFinalized) {
|
|
418
|
+
if (urlInfo.context.dev) {
|
|
419
|
+
throw new Error(
|
|
420
|
+
`cannot add a transform callback on content already sent to the browser.
|
|
421
|
+
--- content url ---
|
|
422
|
+
${urlInfo.url}`,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
urlInfo.context.addLastTransformationCallback(callback);
|
|
426
|
+
} else {
|
|
427
|
+
contentTransformationCallbackSet.add(callback);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
urlInfo.applyContentTransformationCallbacks = async () => {
|
|
431
|
+
for (const contentTransformationCallback of contentTransformationCallbackSet) {
|
|
432
|
+
await contentTransformationCallback();
|
|
433
|
+
}
|
|
434
|
+
contentTransformationCallbackSet.clear();
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
// Object.preventExtensions(urlInfo) // useful to ensure all properties are declared here
|
|
438
|
+
return urlInfo;
|
|
439
|
+
};
|
|
@@ -30,6 +30,9 @@ const createUrlGraphReport = (urlGraph) => {
|
|
|
30
30
|
total: 0,
|
|
31
31
|
};
|
|
32
32
|
urlGraph.urlInfoMap.forEach((urlInfo) => {
|
|
33
|
+
if (urlInfo.isRoot) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
33
36
|
// ignore:
|
|
34
37
|
// - ignored files: we don't know their content
|
|
35
38
|
// - inline files and data files: they are already taken into account in the file where they appear
|
|
@@ -47,11 +50,10 @@ const createUrlGraphReport = (urlGraph) => {
|
|
|
47
50
|
// their js module equivalent are ignored to avoid counting it twice
|
|
48
51
|
// in the build graph the file targeted by import assertion will likely be gone
|
|
49
52
|
// and only the js module remain (likely bundled)
|
|
50
|
-
const urlObject = new URL(urlInfo.url);
|
|
51
53
|
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
urlInfo.searchParams.has("as_json_module") ||
|
|
55
|
+
urlInfo.searchParams.has("as_css_module") ||
|
|
56
|
+
urlInfo.searchParams.has("as_text_module")
|
|
55
57
|
) {
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
@@ -29,7 +29,8 @@ GRAPH_VISITOR.find = (graph, callback) => {
|
|
|
29
29
|
}
|
|
30
30
|
return found;
|
|
31
31
|
};
|
|
32
|
-
GRAPH_VISITOR.findDependent = (
|
|
32
|
+
GRAPH_VISITOR.findDependent = (urlInfo, visitor) => {
|
|
33
|
+
const graph = urlInfo.graph;
|
|
33
34
|
const seen = new Set();
|
|
34
35
|
seen.add(urlInfo.url);
|
|
35
36
|
let found = null;
|
|
@@ -44,9 +45,9 @@ GRAPH_VISITOR.findDependent = (graph, urlInfo, visitor) => {
|
|
|
44
45
|
return true;
|
|
45
46
|
};
|
|
46
47
|
const iterate = (currentUrlInfo) => {
|
|
47
|
-
// When cookin html inline content, html
|
|
48
|
+
// When cookin html inline content, html dependencies are not yet updated
|
|
48
49
|
// consequently htmlUrlInfo.dependencies is empty
|
|
49
|
-
// and inlineContentUrlInfo.
|
|
50
|
+
// and inlineContentUrlInfo.referenceFromOthersSet is empty as well
|
|
50
51
|
// in that case we resort to isInline + inlineUrlSite to establish the dependency
|
|
51
52
|
if (currentUrlInfo.isInline) {
|
|
52
53
|
const parentUrl = currentUrlInfo.inlineUrlSite.url;
|
|
@@ -56,20 +57,21 @@ GRAPH_VISITOR.findDependent = (graph, urlInfo, visitor) => {
|
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
for (const
|
|
60
|
-
const
|
|
61
|
-
if (visit(
|
|
60
|
+
for (const referenceFromOther of currentUrlInfo.referenceFromOthersSet) {
|
|
61
|
+
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
62
|
+
if (visit(urlInfoReferencingThisOne)) {
|
|
62
63
|
if (found) {
|
|
63
64
|
break;
|
|
64
65
|
}
|
|
65
|
-
iterate(
|
|
66
|
+
iterate(urlInfoReferencingThisOne);
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
};
|
|
69
70
|
iterate(urlInfo);
|
|
70
71
|
return found;
|
|
71
72
|
};
|
|
72
|
-
GRAPH_VISITOR.findDependency = (
|
|
73
|
+
GRAPH_VISITOR.findDependency = (urlInfo, visitor) => {
|
|
74
|
+
const graph = urlInfo.graph;
|
|
73
75
|
const seen = new Set();
|
|
74
76
|
seen.add(urlInfo.url);
|
|
75
77
|
let found = null;
|
|
@@ -84,13 +86,13 @@ GRAPH_VISITOR.findDependency = (graph, urlInfo, visitor) => {
|
|
|
84
86
|
return true;
|
|
85
87
|
};
|
|
86
88
|
const iterate = (currentUrlInfo) => {
|
|
87
|
-
for (const
|
|
88
|
-
const
|
|
89
|
-
if (visit(
|
|
89
|
+
for (const referenceToOther of currentUrlInfo.referenceToOthersSet) {
|
|
90
|
+
const referencedUrlInfo = graph.getUrlInfo(referenceToOther);
|
|
91
|
+
if (visit(referencedUrlInfo)) {
|
|
90
92
|
if (found) {
|
|
91
93
|
break;
|
|
92
94
|
}
|
|
93
|
-
iterate(
|
|
95
|
+
iterate(referencedUrlInfo);
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
};
|