@jsenv/core 36.3.1 → 37.0.1
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 +17 -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,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].
|
|
18
|
-
visit(
|
|
17
|
+
nodes[url].referenceToOthersSet.forEach((referenceToOther) => {
|
|
18
|
+
visit(referenceToOther.url, url);
|
|
19
19
|
});
|
|
20
20
|
sorted.push(url);
|
|
21
21
|
}
|