@jsenv/core 37.0.5 → 37.1.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 +23 -20
- package/dist/js/import_meta_hot.js +0 -1
- package/dist/jsenv_core.js +674 -585
- package/package.json +2 -2
- package/src/build/build.js +141 -154
- package/src/build/build_versions_manager.js +53 -56
- package/src/dev/file_service.js +68 -77
- package/src/dev/start_dev_server.js +2 -4
- package/src/helpers/event_emitter.js +18 -0
- package/src/kitchen/kitchen.js +4 -6
- package/src/kitchen/url_graph/references.js +29 -8
- package/src/kitchen/url_graph/url_content.js +9 -0
- package/src/kitchen/url_graph/url_graph.js +46 -57
- package/src/kitchen/url_graph/url_graph_report.js +62 -59
- package/src/kitchen/url_graph/url_graph_visitor.js +30 -0
- package/src/kitchen/url_graph/url_info_transformations.js +26 -26
- package/src/plugins/autoreload/client/autoreload.js +7 -7
- package/src/plugins/autoreload/client/reload.js +16 -13
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +4 -4
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +138 -96
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +43 -25
- package/src/plugins/import_meta_hot/client/import_meta_hot.js +0 -1
- package/src/plugins/plugins.js +3 -14
package/dist/jsenv_core.js
CHANGED
|
@@ -13,7 +13,7 @@ import http from "node:http";
|
|
|
13
13
|
import { Readable, Stream, Writable } from "node:stream";
|
|
14
14
|
import { Http2ServerResponse } from "node:http2";
|
|
15
15
|
import { lookup } from "node:dns";
|
|
16
|
-
import { composeTwoSourcemaps, createMagicSource,
|
|
16
|
+
import { composeTwoSourcemaps, createMagicSource, generateSourcemapFileUrl, SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
17
17
|
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtmlString, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, stringifyHtmlAst, setHtmlNodeAttributes, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, parseJsWithAcorn, parseSrcSet, getHtmlNodeText, getHtmlNodePosition, getHtmlNodeAttributePosition, removeHtmlNodeText, setHtmlNodeText, parseCssUrls, parseJsUrls, findHtmlNode, removeHtmlNode, analyzeLinkNode, injectHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
|
|
18
18
|
import { RUNTIME_COMPAT } from "@jsenv/runtime-compat";
|
|
19
19
|
import { createRequire } from "node:module";
|
|
@@ -5026,6 +5026,7 @@ const getPropertiesFromResource = ({ resource, baseUrl }) => {
|
|
|
5026
5026
|
|
|
5027
5027
|
return {
|
|
5028
5028
|
url: String(urlObject),
|
|
5029
|
+
searchParams: urlObject.searchParams,
|
|
5029
5030
|
pathname,
|
|
5030
5031
|
resource,
|
|
5031
5032
|
};
|
|
@@ -10455,6 +10456,55 @@ GRAPH_VISITOR.findDependency = (urlInfo, visitor) => {
|
|
|
10455
10456
|
return found;
|
|
10456
10457
|
};
|
|
10457
10458
|
|
|
10459
|
+
// This function will be used in "build.js"
|
|
10460
|
+
// by passing rootUrlInfo as first arg
|
|
10461
|
+
// -> this ensure we visit only urls with strong references
|
|
10462
|
+
// because we start from root and ignore weak ref
|
|
10463
|
+
// The alternative would be to iterate on urlInfoMap
|
|
10464
|
+
// and call urlInfo.isUsed() but that would be more expensive
|
|
10465
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced = (initialUrlInfo, callback) => {
|
|
10466
|
+
const seen = new Set();
|
|
10467
|
+
seen.add(initialUrlInfo);
|
|
10468
|
+
const iterateOnReferences = (urlInfo) => {
|
|
10469
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
10470
|
+
if (referenceToOther.isWeak) {
|
|
10471
|
+
continue;
|
|
10472
|
+
}
|
|
10473
|
+
if (referenceToOther.gotInlined()) {
|
|
10474
|
+
continue;
|
|
10475
|
+
}
|
|
10476
|
+
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
10477
|
+
if (seen.has(referencedUrlInfo)) {
|
|
10478
|
+
continue;
|
|
10479
|
+
}
|
|
10480
|
+
seen.add(referencedUrlInfo);
|
|
10481
|
+
callback(referencedUrlInfo);
|
|
10482
|
+
iterateOnReferences(referencedUrlInfo);
|
|
10483
|
+
}
|
|
10484
|
+
};
|
|
10485
|
+
iterateOnReferences(initialUrlInfo);
|
|
10486
|
+
seen.clear();
|
|
10487
|
+
};
|
|
10488
|
+
|
|
10489
|
+
const createEventEmitter = () => {
|
|
10490
|
+
const callbackSet = new Set();
|
|
10491
|
+
const on = (callback) => {
|
|
10492
|
+
callbackSet.add(callback);
|
|
10493
|
+
return () => {
|
|
10494
|
+
callbackSet.delete(callback);
|
|
10495
|
+
};
|
|
10496
|
+
};
|
|
10497
|
+
const off = (callback) => {
|
|
10498
|
+
callbackSet.delete(callback);
|
|
10499
|
+
};
|
|
10500
|
+
const emit = (...args) => {
|
|
10501
|
+
callbackSet.forEach((callback) => {
|
|
10502
|
+
callback(...args);
|
|
10503
|
+
});
|
|
10504
|
+
};
|
|
10505
|
+
return { on, off, emit };
|
|
10506
|
+
};
|
|
10507
|
+
|
|
10458
10508
|
const urlSpecifierEncoding = {
|
|
10459
10509
|
encode: (reference) => {
|
|
10460
10510
|
const { generatedSpecifier } = reference;
|
|
@@ -11116,6 +11166,10 @@ const createReference = ({
|
|
|
11116
11166
|
return implicitReference;
|
|
11117
11167
|
};
|
|
11118
11168
|
|
|
11169
|
+
reference.gotInlined = () => {
|
|
11170
|
+
return !reference.isInline && reference.next && reference.next.isInline;
|
|
11171
|
+
};
|
|
11172
|
+
|
|
11119
11173
|
reference.remove = () => removeDependency(reference);
|
|
11120
11174
|
|
|
11121
11175
|
// Object.preventExtensions(reference) // useful to ensure all properties are declared here
|
|
@@ -11210,7 +11264,6 @@ const canAddOrRemoveReference = (reference) => {
|
|
|
11210
11264
|
const applyDependencyRemovalEffects = (reference) => {
|
|
11211
11265
|
const { ownerUrlInfo } = reference;
|
|
11212
11266
|
const { referenceToOthersSet } = ownerUrlInfo;
|
|
11213
|
-
|
|
11214
11267
|
if (reference.isImplicit && !reference.isInline) {
|
|
11215
11268
|
let hasAnOtherImplicitRef = false;
|
|
11216
11269
|
for (const referenceToOther of referenceToOthersSet) {
|
|
@@ -11242,8 +11295,29 @@ const applyDependencyRemovalEffects = (reference) => {
|
|
|
11242
11295
|
const referencedUrlInfo = reference.urlInfo;
|
|
11243
11296
|
referencedUrlInfo.referenceFromOthersSet.delete(reference);
|
|
11244
11297
|
|
|
11245
|
-
|
|
11246
|
-
|
|
11298
|
+
let firstReferenceFromOther;
|
|
11299
|
+
for (const referenceFromOther of referencedUrlInfo.referenceFromOthersSet) {
|
|
11300
|
+
if (referenceFromOther.urlInfo !== referencedUrlInfo) {
|
|
11301
|
+
continue;
|
|
11302
|
+
}
|
|
11303
|
+
// Here we want to know if the file is referenced by an other file.
|
|
11304
|
+
// So we want to ignore reference that are created by other means:
|
|
11305
|
+
// - "http_request"
|
|
11306
|
+
// This type of reference is created when client request a file
|
|
11307
|
+
// that we don't know yet
|
|
11308
|
+
// 1. reference(s) to this file are not yet discovered
|
|
11309
|
+
// 2. there is no reference to this file
|
|
11310
|
+
if (referenceFromOther.type === "http_request") {
|
|
11311
|
+
continue;
|
|
11312
|
+
}
|
|
11313
|
+
if (referenceFromOther.gotInlined()) {
|
|
11314
|
+
// the url info was inlined, an other reference is required
|
|
11315
|
+
// to consider the non-inlined urlInfo as used
|
|
11316
|
+
continue;
|
|
11317
|
+
}
|
|
11318
|
+
firstReferenceFromOther = referenceFromOther;
|
|
11319
|
+
break;
|
|
11320
|
+
}
|
|
11247
11321
|
if (firstReferenceFromOther) {
|
|
11248
11322
|
// either applying new ref should override old ref
|
|
11249
11323
|
// or we should first remove effects before adding new ones
|
|
@@ -11254,11 +11328,8 @@ const applyDependencyRemovalEffects = (reference) => {
|
|
|
11254
11328
|
}
|
|
11255
11329
|
return false;
|
|
11256
11330
|
}
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
return true;
|
|
11260
|
-
}
|
|
11261
|
-
return false;
|
|
11331
|
+
referencedUrlInfo.onDereferenced(reference);
|
|
11332
|
+
return true;
|
|
11262
11333
|
};
|
|
11263
11334
|
|
|
11264
11335
|
const traceFromUrlSite = (urlSite) => {
|
|
@@ -11371,8 +11442,8 @@ const createUrlGraph = ({
|
|
|
11371
11442
|
name = "anonymous",
|
|
11372
11443
|
}) => {
|
|
11373
11444
|
const urlGraph = {};
|
|
11374
|
-
const
|
|
11375
|
-
const
|
|
11445
|
+
const urlInfoCreatedEventEmitter = createEventEmitter();
|
|
11446
|
+
const urlInfoDereferencedEventEmitter = createEventEmitter();
|
|
11376
11447
|
|
|
11377
11448
|
const urlInfoMap = new Map();
|
|
11378
11449
|
const hasUrlInfo = (key) => {
|
|
@@ -11393,27 +11464,7 @@ const createUrlGraph = ({
|
|
|
11393
11464
|
}
|
|
11394
11465
|
return null;
|
|
11395
11466
|
};
|
|
11396
|
-
|
|
11397
|
-
const urlInfo = urlInfoMap.get(url);
|
|
11398
|
-
if (urlInfo) {
|
|
11399
|
-
urlInfo.kitchen.urlInfoTransformer.resetContent(urlInfo);
|
|
11400
|
-
urlInfoMap.delete(url);
|
|
11401
|
-
urlInfo.modifiedTimestamp = Date.now();
|
|
11402
|
-
if (lastReferenceFromOther && !urlInfo.isInline) {
|
|
11403
|
-
pruneUrlInfoCallbackRef.current(urlInfo, lastReferenceFromOther);
|
|
11404
|
-
}
|
|
11405
|
-
urlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
11406
|
-
referenceToOther.remove();
|
|
11407
|
-
});
|
|
11408
|
-
if (urlInfo.searchParams.size > 0) {
|
|
11409
|
-
const urlWithoutSearch = asUrlWithoutSearch(urlInfo.url);
|
|
11410
|
-
const urlInfoWithoutSearch = getUrlInfo(urlWithoutSearch);
|
|
11411
|
-
if (urlInfoWithoutSearch) {
|
|
11412
|
-
urlInfoWithoutSearch.searchParamVariantSet.delete(urlInfo);
|
|
11413
|
-
}
|
|
11414
|
-
}
|
|
11415
|
-
}
|
|
11416
|
-
};
|
|
11467
|
+
|
|
11417
11468
|
const addUrlInfo = (urlInfo) => {
|
|
11418
11469
|
urlInfo.graph = urlGraph;
|
|
11419
11470
|
urlInfo.kitchen = kitchen;
|
|
@@ -11430,7 +11481,7 @@ const createUrlGraph = ({
|
|
|
11430
11481
|
const context = Object.create(ownerContext);
|
|
11431
11482
|
referencedUrlInfo = createUrlInfo(referencedUrl, context);
|
|
11432
11483
|
addUrlInfo(referencedUrlInfo);
|
|
11433
|
-
|
|
11484
|
+
urlInfoCreatedEventEmitter.emit(referencedUrlInfo);
|
|
11434
11485
|
}
|
|
11435
11486
|
if (referencedUrlInfo.searchParams.size > 0 && !kitchen.context.shape) {
|
|
11436
11487
|
// A resource is represented by a url.
|
|
@@ -11507,17 +11558,16 @@ const createUrlGraph = ({
|
|
|
11507
11558
|
Object.assign(urlGraph, {
|
|
11508
11559
|
name,
|
|
11509
11560
|
rootUrlInfo,
|
|
11510
|
-
createUrlInfoCallbackRef,
|
|
11511
|
-
pruneUrlInfoCallbackRef,
|
|
11512
11561
|
|
|
11513
11562
|
urlInfoMap,
|
|
11514
11563
|
reuseOrCreateUrlInfo,
|
|
11515
11564
|
hasUrlInfo,
|
|
11516
11565
|
getUrlInfo,
|
|
11517
|
-
deleteUrlInfo,
|
|
11518
11566
|
getEntryPoints,
|
|
11519
11567
|
|
|
11520
11568
|
inferReference,
|
|
11569
|
+
urlInfoCreatedEventEmitter,
|
|
11570
|
+
urlInfoDereferencedEventEmitter,
|
|
11521
11571
|
|
|
11522
11572
|
toObject: () => {
|
|
11523
11573
|
const data = {};
|
|
@@ -11555,6 +11605,7 @@ const createUrlInfo = (url, context) => {
|
|
|
11555
11605
|
context,
|
|
11556
11606
|
error: null,
|
|
11557
11607
|
modifiedTimestamp: 0,
|
|
11608
|
+
dereferencedTimestamp: 0,
|
|
11558
11609
|
originalContentEtag: null,
|
|
11559
11610
|
contentEtag: null,
|
|
11560
11611
|
isWatched: false,
|
|
@@ -11579,6 +11630,7 @@ const createUrlInfo = (url, context) => {
|
|
|
11579
11630
|
originalContentAst: undefined,
|
|
11580
11631
|
content: undefined,
|
|
11581
11632
|
contentAst: undefined,
|
|
11633
|
+
contentLength: undefined,
|
|
11582
11634
|
contentFinalized: false,
|
|
11583
11635
|
|
|
11584
11636
|
sourcemap: null,
|
|
@@ -11605,37 +11657,24 @@ const createUrlInfo = (url, context) => {
|
|
|
11605
11657
|
urlInfo.searchParams = new URL(url).searchParams;
|
|
11606
11658
|
|
|
11607
11659
|
urlInfo.dependencies = createDependencies(urlInfo);
|
|
11608
|
-
urlInfo.getFirstReferenceFromOther = ({ ignoreWeak } = {}) => {
|
|
11609
|
-
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
11610
|
-
if (referenceFromOther.url === urlInfo.url) {
|
|
11611
|
-
if (
|
|
11612
|
-
!referenceFromOther.isInline &&
|
|
11613
|
-
referenceFromOther.next &&
|
|
11614
|
-
referenceFromOther.next.isInline
|
|
11615
|
-
) {
|
|
11616
|
-
// the url info was inlined, an other reference is required
|
|
11617
|
-
// to consider the non-inlined urlInfo as used
|
|
11618
|
-
continue;
|
|
11619
|
-
}
|
|
11620
|
-
if (ignoreWeak && referenceFromOther.isWeak) {
|
|
11621
|
-
// weak reference don't count as using the url
|
|
11622
|
-
continue;
|
|
11623
|
-
}
|
|
11624
|
-
return referenceFromOther;
|
|
11625
|
-
}
|
|
11626
|
-
}
|
|
11627
|
-
return null;
|
|
11628
|
-
};
|
|
11629
11660
|
urlInfo.isUsed = () => {
|
|
11630
11661
|
if (urlInfo.isRoot) {
|
|
11631
11662
|
return true;
|
|
11632
11663
|
}
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11664
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
11665
|
+
if (referenceFromOther.urlInfo !== urlInfo) {
|
|
11666
|
+
continue;
|
|
11667
|
+
}
|
|
11668
|
+
if (referenceFromOther.isWeak) {
|
|
11669
|
+
// weak reference don't count as using the url
|
|
11670
|
+
continue;
|
|
11671
|
+
}
|
|
11672
|
+
if (referenceFromOther.gotInlined()) {
|
|
11673
|
+
// the url info was inlined, an other reference is required
|
|
11674
|
+
// to consider the non-inlined urlInfo as used
|
|
11675
|
+
continue;
|
|
11676
|
+
}
|
|
11677
|
+
return referenceFromOther.ownerUrlInfo.isUsed();
|
|
11639
11678
|
}
|
|
11640
11679
|
// nothing uses this url anymore
|
|
11641
11680
|
// - versioning update inline content
|
|
@@ -11725,7 +11764,7 @@ const createUrlInfo = (url, context) => {
|
|
|
11725
11764
|
reference.next = referenceWithoutSearchParam;
|
|
11726
11765
|
return referenceWithoutSearchParam.urlInfo;
|
|
11727
11766
|
};
|
|
11728
|
-
urlInfo.
|
|
11767
|
+
urlInfo.onModified = ({ modifiedTimestamp = Date.now() } = {}) => {
|
|
11729
11768
|
const visitedSet = new Set();
|
|
11730
11769
|
const iterate = (urlInfo) => {
|
|
11731
11770
|
if (visitedSet.has(urlInfo)) {
|
|
@@ -11746,9 +11785,29 @@ const createUrlInfo = (url, context) => {
|
|
|
11746
11785
|
};
|
|
11747
11786
|
iterate(urlInfo);
|
|
11748
11787
|
};
|
|
11749
|
-
urlInfo.
|
|
11750
|
-
urlInfo.
|
|
11788
|
+
urlInfo.onDereferenced = (lastReferenceFromOther) => {
|
|
11789
|
+
urlInfo.dereferencedTimestamp = Date.now();
|
|
11790
|
+
urlInfo.graph.urlInfoDereferencedEventEmitter.emit(
|
|
11791
|
+
urlInfo,
|
|
11792
|
+
lastReferenceFromOther,
|
|
11793
|
+
);
|
|
11751
11794
|
};
|
|
11795
|
+
|
|
11796
|
+
// not used for now
|
|
11797
|
+
// urlInfo.deleteFromGraph = () => {
|
|
11798
|
+
// urlInfo.kitchen.urlInfoTransformer.resetContent(urlInfo);
|
|
11799
|
+
// urlInfo.graph.urlInfoMap.delete(url);
|
|
11800
|
+
// urlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
11801
|
+
// referenceToOther.remove();
|
|
11802
|
+
// });
|
|
11803
|
+
// if (urlInfo.searchParams.size > 0) {
|
|
11804
|
+
// const urlWithoutSearch = asUrlWithoutSearch(urlInfo.url);
|
|
11805
|
+
// const urlInfoWithoutSearch = urlInfo.graph.getUrlInfo(urlWithoutSearch);
|
|
11806
|
+
// if (urlInfoWithoutSearch) {
|
|
11807
|
+
// urlInfoWithoutSearch.searchParamVariantSet.delete(urlInfo);
|
|
11808
|
+
// }
|
|
11809
|
+
// }
|
|
11810
|
+
// };
|
|
11752
11811
|
urlInfo.cook = (customContext) => {
|
|
11753
11812
|
return urlInfo.context.cook(urlInfo, customContext);
|
|
11754
11813
|
};
|
|
@@ -12231,6 +12290,15 @@ const defineGettersOnPropertiesDerivedFromOriginalContent = (
|
|
|
12231
12290
|
};
|
|
12232
12291
|
|
|
12233
12292
|
const defineGettersOnPropertiesDerivedFromContent = (urlInfo) => {
|
|
12293
|
+
const contentLengthDescriptor = Object.getOwnPropertyDescriptor(
|
|
12294
|
+
urlInfo,
|
|
12295
|
+
"contentLength",
|
|
12296
|
+
);
|
|
12297
|
+
if (contentLengthDescriptor.value === undefined) {
|
|
12298
|
+
defineVolatileGetter(urlInfo, "contentLength", () => {
|
|
12299
|
+
return Buffer.byteLength(urlInfo.content);
|
|
12300
|
+
});
|
|
12301
|
+
}
|
|
12234
12302
|
const contentAstDescriptor = Object.getOwnPropertyDescriptor(
|
|
12235
12303
|
urlInfo,
|
|
12236
12304
|
"contentAst",
|
|
@@ -12317,11 +12385,6 @@ const createUrlInfoTransformer = ({
|
|
|
12317
12385
|
sourcemapsSourcesContent = true;
|
|
12318
12386
|
}
|
|
12319
12387
|
|
|
12320
|
-
const sourcemapsEnabled =
|
|
12321
|
-
sourcemaps === "inline" ||
|
|
12322
|
-
sourcemaps === "file" ||
|
|
12323
|
-
sourcemaps === "programmatic";
|
|
12324
|
-
|
|
12325
12388
|
const normalizeSourcemap = (urlInfo, sourcemap) => {
|
|
12326
12389
|
let { sources } = sourcemap;
|
|
12327
12390
|
if (sources) {
|
|
@@ -12364,15 +12427,10 @@ const createUrlInfoTransformer = ({
|
|
|
12364
12427
|
urlInfo.originalContentEtag = undefined;
|
|
12365
12428
|
urlInfo.contentAst = undefined;
|
|
12366
12429
|
urlInfo.contentEtag = undefined;
|
|
12430
|
+
urlInfo.contentLength = undefined;
|
|
12367
12431
|
urlInfo.content = undefined;
|
|
12368
12432
|
urlInfo.sourcemap = null;
|
|
12369
12433
|
urlInfo.sourcemapIsWrong = null;
|
|
12370
|
-
urlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
12371
|
-
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
12372
|
-
if (referencedUrlInfo.isInline) {
|
|
12373
|
-
referencedUrlInfo.deleteFromGraph();
|
|
12374
|
-
}
|
|
12375
|
-
});
|
|
12376
12434
|
};
|
|
12377
12435
|
|
|
12378
12436
|
const setContent = async (
|
|
@@ -12381,6 +12439,7 @@ const createUrlInfoTransformer = ({
|
|
|
12381
12439
|
{
|
|
12382
12440
|
contentAst, // most of the time will be undefined
|
|
12383
12441
|
contentEtag, // in practice it's always undefined
|
|
12442
|
+
contentLength,
|
|
12384
12443
|
originalContent = content,
|
|
12385
12444
|
originalContentAst, // most of the time will be undefined
|
|
12386
12445
|
originalContentEtag, // in practice always undefined
|
|
@@ -12396,17 +12455,12 @@ const createUrlInfoTransformer = ({
|
|
|
12396
12455
|
|
|
12397
12456
|
urlInfo.contentAst = contentAst;
|
|
12398
12457
|
urlInfo.contentEtag = contentEtag;
|
|
12458
|
+
urlInfo.contentLength = contentLength;
|
|
12399
12459
|
urlInfo.content = content;
|
|
12400
12460
|
defineGettersOnPropertiesDerivedFromContent(urlInfo);
|
|
12401
12461
|
|
|
12402
12462
|
urlInfo.sourcemap = sourcemap;
|
|
12403
|
-
if (!
|
|
12404
|
-
return;
|
|
12405
|
-
}
|
|
12406
|
-
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
12407
|
-
return;
|
|
12408
|
-
}
|
|
12409
|
-
if (urlInfo.generatedUrl.startsWith("data:")) {
|
|
12463
|
+
if (!shouldHandleSourcemap(urlInfo)) {
|
|
12410
12464
|
return;
|
|
12411
12465
|
}
|
|
12412
12466
|
// sourcemap is a special kind of reference:
|
|
@@ -12469,6 +12523,7 @@ const createUrlInfoTransformer = ({
|
|
|
12469
12523
|
content,
|
|
12470
12524
|
contentAst, // undefined most of the time
|
|
12471
12525
|
contentEtag, // in practice always undefined
|
|
12526
|
+
contentLength,
|
|
12472
12527
|
sourcemap,
|
|
12473
12528
|
sourcemapIsWrong,
|
|
12474
12529
|
} = transformations;
|
|
@@ -12482,10 +12537,11 @@ const createUrlInfoTransformer = ({
|
|
|
12482
12537
|
if (contentModified) {
|
|
12483
12538
|
urlInfo.contentAst = contentAst;
|
|
12484
12539
|
urlInfo.contentEtag = contentEtag;
|
|
12540
|
+
urlInfo.contentLength = contentLength;
|
|
12485
12541
|
urlInfo.content = content;
|
|
12486
12542
|
defineGettersOnPropertiesDerivedFromContent(urlInfo);
|
|
12487
12543
|
}
|
|
12488
|
-
if (
|
|
12544
|
+
if (sourcemap && shouldHandleSourcemap(urlInfo)) {
|
|
12489
12545
|
const sourcemapNormalized = normalizeSourcemap(urlInfo, sourcemap);
|
|
12490
12546
|
const finalSourcemap = composeTwoSourcemaps(
|
|
12491
12547
|
urlInfo.sourcemap,
|
|
@@ -12561,13 +12617,7 @@ const createUrlInfoTransformer = ({
|
|
|
12561
12617
|
};
|
|
12562
12618
|
|
|
12563
12619
|
const applySourcemapOnContent = (urlInfo) => {
|
|
12564
|
-
if (!
|
|
12565
|
-
return;
|
|
12566
|
-
}
|
|
12567
|
-
if (!urlInfo.sourcemap) {
|
|
12568
|
-
return;
|
|
12569
|
-
}
|
|
12570
|
-
if (urlInfo.generatedUrl.startsWith("data:")) {
|
|
12620
|
+
if (!urlInfo.sourcemap || !shouldHandleSourcemap(urlInfo)) {
|
|
12571
12621
|
return;
|
|
12572
12622
|
}
|
|
12573
12623
|
|
|
@@ -12653,6 +12703,24 @@ const createUrlInfoTransformer = ({
|
|
|
12653
12703
|
};
|
|
12654
12704
|
};
|
|
12655
12705
|
|
|
12706
|
+
const shouldHandleSourcemap = (urlInfo) => {
|
|
12707
|
+
const { sourcemaps } = urlInfo.context;
|
|
12708
|
+
if (
|
|
12709
|
+
sourcemaps !== "inline" &&
|
|
12710
|
+
sourcemaps !== "file" &&
|
|
12711
|
+
sourcemaps !== "programmatic"
|
|
12712
|
+
) {
|
|
12713
|
+
return false;
|
|
12714
|
+
}
|
|
12715
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
12716
|
+
return false;
|
|
12717
|
+
}
|
|
12718
|
+
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
12719
|
+
return false;
|
|
12720
|
+
}
|
|
12721
|
+
return true;
|
|
12722
|
+
};
|
|
12723
|
+
|
|
12656
12724
|
const createResolveUrlError = ({
|
|
12657
12725
|
pluginController,
|
|
12658
12726
|
reference,
|
|
@@ -13489,12 +13557,10 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
13489
13557
|
// "cooked" hook
|
|
13490
13558
|
pluginController.callHooks("cooked", urlInfo, (cookedReturnValue) => {
|
|
13491
13559
|
if (typeof cookedReturnValue === "function") {
|
|
13492
|
-
const
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
if (prunedUrlInfo === urlInfo.url) {
|
|
13497
|
-
graph.pruneUrlInfoCallbackRef.current = prevCallback;
|
|
13560
|
+
const removeCallback = urlInfo.graph.urlInfoDereferencedEventEmitter.on(
|
|
13561
|
+
(urlInfoDereferenced, lastReferenceFromOther) => {
|
|
13562
|
+
if (urlInfoDereferenced === urlInfo) {
|
|
13563
|
+
removeCallback();
|
|
13498
13564
|
cookedReturnValue(lastReferenceFromOther.urlInfo);
|
|
13499
13565
|
}
|
|
13500
13566
|
},
|
|
@@ -13726,67 +13792,69 @@ const createUrlGraphReport = (urlGraph) => {
|
|
|
13726
13792
|
other: 0,
|
|
13727
13793
|
total: 0,
|
|
13728
13794
|
};
|
|
13729
|
-
urlGraph.urlInfoMap.forEach((urlInfo) => {
|
|
13730
|
-
if (urlInfo.isRoot) {
|
|
13731
|
-
return;
|
|
13732
|
-
}
|
|
13733
|
-
// ignore:
|
|
13734
|
-
// - ignored files: we don't know their content
|
|
13735
|
-
// - inline files and data files: they are already taken into account in the file where they appear
|
|
13736
|
-
if (urlInfo.url.startsWith("ignore:")) {
|
|
13737
|
-
return;
|
|
13738
|
-
}
|
|
13739
|
-
if (urlInfo.isInline) {
|
|
13740
|
-
return;
|
|
13741
|
-
}
|
|
13742
|
-
if (urlInfo.url.startsWith("data:")) {
|
|
13743
|
-
return;
|
|
13744
|
-
}
|
|
13745
13795
|
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
urlInfo.
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
|
|
13764
|
-
|
|
13765
|
-
|
|
13766
|
-
|
|
13767
|
-
|
|
13768
|
-
|
|
13769
|
-
|
|
13770
|
-
|
|
13771
|
-
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13775
|
-
|
|
13776
|
-
|
|
13777
|
-
|
|
13778
|
-
|
|
13779
|
-
|
|
13780
|
-
|
|
13781
|
-
|
|
13782
|
-
|
|
13783
|
-
|
|
13796
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
13797
|
+
urlGraph.rootUrlInfo,
|
|
13798
|
+
(urlInfo) => {
|
|
13799
|
+
// ignore:
|
|
13800
|
+
// - ignored files: we don't know their content
|
|
13801
|
+
// - inline files and data files: they are already taken into account in the file where they appear
|
|
13802
|
+
if (urlInfo.url.startsWith("ignore:")) {
|
|
13803
|
+
return;
|
|
13804
|
+
}
|
|
13805
|
+
if (urlInfo.isInline) {
|
|
13806
|
+
return;
|
|
13807
|
+
}
|
|
13808
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
13809
|
+
return;
|
|
13810
|
+
}
|
|
13811
|
+
|
|
13812
|
+
// file loaded via import assertion are already inside the graph
|
|
13813
|
+
// their js module equivalent are ignored to avoid counting it twice
|
|
13814
|
+
// in the build graph the file targeted by import assertion will likely be gone
|
|
13815
|
+
// and only the js module remain (likely bundled)
|
|
13816
|
+
if (
|
|
13817
|
+
urlInfo.searchParams.has("as_json_module") ||
|
|
13818
|
+
urlInfo.searchParams.has("as_css_module") ||
|
|
13819
|
+
urlInfo.searchParams.has("as_text_module")
|
|
13820
|
+
) {
|
|
13821
|
+
return;
|
|
13822
|
+
}
|
|
13823
|
+
|
|
13824
|
+
const urlContentSize = Buffer.byteLength(urlInfo.content);
|
|
13825
|
+
const category = determineCategory(urlInfo);
|
|
13826
|
+
if (category === "sourcemap") {
|
|
13827
|
+
countGroups.sourcemaps++;
|
|
13828
|
+
sizeGroups.sourcemaps += urlContentSize;
|
|
13829
|
+
return;
|
|
13830
|
+
}
|
|
13831
|
+
countGroups.total++;
|
|
13832
|
+
sizeGroups.total += urlContentSize;
|
|
13833
|
+
if (category === "html") {
|
|
13834
|
+
countGroups.html++;
|
|
13835
|
+
sizeGroups.html += urlContentSize;
|
|
13836
|
+
return;
|
|
13837
|
+
}
|
|
13838
|
+
if (category === "css") {
|
|
13839
|
+
countGroups.css++;
|
|
13840
|
+
sizeGroups.css += urlContentSize;
|
|
13841
|
+
return;
|
|
13842
|
+
}
|
|
13843
|
+
if (category === "js") {
|
|
13844
|
+
countGroups.js++;
|
|
13845
|
+
sizeGroups.js += urlContentSize;
|
|
13846
|
+
return;
|
|
13847
|
+
}
|
|
13848
|
+
if (category === "json") {
|
|
13849
|
+
countGroups.json++;
|
|
13850
|
+
sizeGroups.json += urlContentSize;
|
|
13851
|
+
return;
|
|
13852
|
+
}
|
|
13853
|
+
countGroups.other++;
|
|
13854
|
+
sizeGroups.other += urlContentSize;
|
|
13784
13855
|
return;
|
|
13785
|
-
}
|
|
13786
|
-
|
|
13787
|
-
sizeGroups.other += urlContentSize;
|
|
13788
|
-
return;
|
|
13789
|
-
});
|
|
13856
|
+
},
|
|
13857
|
+
);
|
|
13790
13858
|
|
|
13791
13859
|
const sizesToDistribute = {};
|
|
13792
13860
|
Object.keys(sizeGroups).forEach((groupName) => {
|
|
@@ -18194,27 +18262,20 @@ import.meta.hot = createImportMetaHot(import.meta.url);
|
|
|
18194
18262
|
return magicSource.toContentAndSourcemap();
|
|
18195
18263
|
};
|
|
18196
18264
|
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
|
|
18205
|
-
|
|
18206
|
-
|
|
18207
|
-
|
|
18208
|
-
|
|
18209
|
-
lastReference &&
|
|
18210
|
-
lastReference.original &&
|
|
18211
|
-
lastReference.original.searchParams.has("hot")
|
|
18212
|
-
) {
|
|
18213
|
-
return true;
|
|
18214
|
-
}
|
|
18215
|
-
return false;
|
|
18216
|
-
};
|
|
18265
|
+
/*
|
|
18266
|
+
* When client wants to hot reload, it wants to be sure it can reach the server
|
|
18267
|
+
* and bypass any cache. This is done thanks to "hot" search param
|
|
18268
|
+
* being injected by the client: file.js?hot=Date.now()
|
|
18269
|
+
* When it happens server must:
|
|
18270
|
+
* 1. Consider it's a regular request to "file.js" and not a variation
|
|
18271
|
+
* of it (not like file.js?as_js_classic that creates a separate urlInfo)
|
|
18272
|
+
* -> This is done by redirectReference deleting the search param.
|
|
18273
|
+
*
|
|
18274
|
+
* 2. Inject ?hot= into all urls referenced by this one
|
|
18275
|
+
* -> This is done by transformReferenceSearchParams
|
|
18276
|
+
*/
|
|
18217
18277
|
|
|
18278
|
+
const jsenvPluginHotSearchParam = () => {
|
|
18218
18279
|
return {
|
|
18219
18280
|
name: "jsenv:hot_search_param",
|
|
18220
18281
|
appliesDuring: "dev",
|
|
@@ -18228,20 +18289,45 @@ const jsenvPluginHotSearchParam = () => {
|
|
|
18228
18289
|
// We get rid of this params so that urlGraph and other parts of the code
|
|
18229
18290
|
// recognize the url (it is not considered as a different url)
|
|
18230
18291
|
urlObject.searchParams.delete("hot");
|
|
18231
|
-
urlObject.searchParams.delete("v");
|
|
18232
18292
|
return urlObject.href;
|
|
18233
18293
|
},
|
|
18234
18294
|
transformReferenceSearchParams: (reference) => {
|
|
18235
|
-
if (
|
|
18295
|
+
if (reference.isImplicit) {
|
|
18236
18296
|
return null;
|
|
18237
18297
|
}
|
|
18298
|
+
if (reference.original && reference.original.searchParams.has("hot")) {
|
|
18299
|
+
return {
|
|
18300
|
+
hot: reference.original.searchParams.get("hot"),
|
|
18301
|
+
};
|
|
18302
|
+
}
|
|
18303
|
+
const request = reference.ownerUrlInfo.context.request;
|
|
18304
|
+
const parentHotParam = request ? request.searchParams.get("hot") : null;
|
|
18305
|
+
if (!parentHotParam) {
|
|
18306
|
+
return null;
|
|
18307
|
+
}
|
|
18308
|
+
// At this stage the parent is using ?hot and we are going to decide if
|
|
18309
|
+
// we propagate the search param to child.
|
|
18238
18310
|
const referencedUrlInfo = reference.urlInfo;
|
|
18239
|
-
|
|
18311
|
+
const { modifiedTimestamp, dereferencedTimestamp } = referencedUrlInfo;
|
|
18312
|
+
if (!modifiedTimestamp && !dereferencedTimestamp) {
|
|
18240
18313
|
return null;
|
|
18241
18314
|
}
|
|
18315
|
+
// The goal is to send an url that will bypass client (the browser) cache
|
|
18316
|
+
// more precisely the runtime cache of js modules, but also any http cache
|
|
18317
|
+
// that could prevent re-execution of js code
|
|
18318
|
+
// In order to achieve this, this plugin inject ?hot=timestamp
|
|
18319
|
+
// - The browser will likely not have it in cache
|
|
18320
|
+
// and refetch lastest version from server + re-execute it
|
|
18321
|
+
// - If the browser have it in cache, he will not get it from server
|
|
18322
|
+
// We use the latest timestamp to ensure it's fresh
|
|
18323
|
+
// The dereferencedTimestamp is needed because when a js module is re-referenced
|
|
18324
|
+
// browser must re-execute it, even if the code is not modified
|
|
18325
|
+
const latestTimestamp =
|
|
18326
|
+
dereferencedTimestamp && modifiedTimestamp
|
|
18327
|
+
? Math.max(dereferencedTimestamp, modifiedTimestamp)
|
|
18328
|
+
: dereferencedTimestamp || modifiedTimestamp;
|
|
18242
18329
|
return {
|
|
18243
|
-
hot:
|
|
18244
|
-
v: referencedUrlInfo.modifiedTimestamp,
|
|
18330
|
+
hot: latestTimestamp,
|
|
18245
18331
|
};
|
|
18246
18332
|
},
|
|
18247
18333
|
};
|
|
@@ -18284,8 +18370,8 @@ const jsenvPluginAutoreloadClient = () => {
|
|
|
18284
18370
|
};
|
|
18285
18371
|
|
|
18286
18372
|
const jsenvPluginAutoreloadServer = ({
|
|
18287
|
-
|
|
18288
|
-
|
|
18373
|
+
clientFileChangeEventEmitter,
|
|
18374
|
+
clientFileDereferencedEventEmitter,
|
|
18289
18375
|
}) => {
|
|
18290
18376
|
return {
|
|
18291
18377
|
name: "jsenv:autoreload_server",
|
|
@@ -18301,29 +18387,7 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
18301
18387
|
}
|
|
18302
18388
|
return url;
|
|
18303
18389
|
};
|
|
18304
|
-
const notifyFullReload = ({ cause, reason, declinedBy }) => {
|
|
18305
|
-
serverEventInfo.sendServerEvent({
|
|
18306
|
-
cause,
|
|
18307
|
-
type: "full",
|
|
18308
|
-
typeReason: reason,
|
|
18309
|
-
declinedBy,
|
|
18310
|
-
});
|
|
18311
|
-
};
|
|
18312
|
-
const notifyPartialReload = ({ cause, reason, instructions }) => {
|
|
18313
|
-
serverEventInfo.sendServerEvent({
|
|
18314
|
-
cause,
|
|
18315
|
-
type: "hot",
|
|
18316
|
-
typeReason: reason,
|
|
18317
|
-
hotInstructions: instructions,
|
|
18318
|
-
});
|
|
18319
|
-
};
|
|
18320
18390
|
const propagateUpdate = (firstUrlInfo) => {
|
|
18321
|
-
if (!serverEventInfo.kitchen.graph.getUrlInfo(firstUrlInfo.url)) {
|
|
18322
|
-
return {
|
|
18323
|
-
declined: true,
|
|
18324
|
-
reason: `url not in the url graph`,
|
|
18325
|
-
};
|
|
18326
|
-
}
|
|
18327
18391
|
const iterate = (urlInfo, seen) => {
|
|
18328
18392
|
if (urlInfo.data.hotAcceptSelf) {
|
|
18329
18393
|
return {
|
|
@@ -18402,86 +18466,150 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
18402
18466
|
const seen = [];
|
|
18403
18467
|
return iterate(firstUrlInfo, seen);
|
|
18404
18468
|
};
|
|
18405
|
-
clientFileChangeCallbackList.push(({ url, event }) => {
|
|
18406
|
-
const onUrlInfo = (urlInfo) => {
|
|
18407
|
-
if (!urlInfo.isUsed()) {
|
|
18408
|
-
return false;
|
|
18409
|
-
}
|
|
18410
|
-
const relativeUrl = formatUrlForClient(urlInfo.url);
|
|
18411
|
-
const hotUpdate = propagateUpdate(urlInfo);
|
|
18412
|
-
if (hotUpdate.declined) {
|
|
18413
|
-
notifyFullReload({
|
|
18414
|
-
cause: `${relativeUrl} ${event}`,
|
|
18415
|
-
reason: hotUpdate.reason,
|
|
18416
|
-
declinedBy: hotUpdate.declinedBy,
|
|
18417
|
-
});
|
|
18418
|
-
return true;
|
|
18419
|
-
}
|
|
18420
|
-
notifyPartialReload({
|
|
18421
|
-
cause: `${relativeUrl} ${event}`,
|
|
18422
|
-
reason: hotUpdate.reason,
|
|
18423
|
-
instructions: hotUpdate.instructions,
|
|
18424
|
-
});
|
|
18425
|
-
return true;
|
|
18426
|
-
};
|
|
18427
18469
|
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18470
|
+
// We are delaying the moment we tell client how to reload because:
|
|
18471
|
+
//
|
|
18472
|
+
// 1. clientFileDereferencedEventEmitter can emit multiple times in a row
|
|
18473
|
+
// It happens when previous references are removed by stopCollecting (in "references.js")
|
|
18474
|
+
// In that case we could regroup the calls but we prefer to rely on debouncing to also cover
|
|
18475
|
+
// code that would remove many url in a row by other means (like reference.remove())
|
|
18476
|
+
//
|
|
18477
|
+
// 2. clientFileChangeEventEmitter can emit a lot of times in a short period (git checkout for instance)
|
|
18478
|
+
// In that case it's better to cooldown thanks to debouncing
|
|
18479
|
+
//
|
|
18480
|
+
// And we want to gather all the actions to take in response to these events because
|
|
18481
|
+
// we want to favor full-reload when needed and resort to partial reload afterwards
|
|
18482
|
+
// it's also important to ensure the client will fetch the server in the same order
|
|
18483
|
+
const delayedActionSet = new Set();
|
|
18484
|
+
let timeout;
|
|
18485
|
+
const delayAction = (action) => {
|
|
18486
|
+
delayedActionSet.add(action);
|
|
18487
|
+
clearTimeout(timeout);
|
|
18488
|
+
timeout = setTimeout(handleDelayedActions);
|
|
18489
|
+
};
|
|
18490
|
+
|
|
18491
|
+
const handleDelayedActions = () => {
|
|
18492
|
+
const actionSet = new Set(delayedActionSet);
|
|
18493
|
+
delayedActionSet.clear();
|
|
18494
|
+
let reloadMessage = null;
|
|
18495
|
+
for (const action of actionSet) {
|
|
18496
|
+
if (action.type === "change") {
|
|
18497
|
+
const { changedUrlInfo, event } = action;
|
|
18498
|
+
if (!changedUrlInfo.isUsed()) {
|
|
18499
|
+
continue;
|
|
18500
|
+
}
|
|
18501
|
+
const hotUpdate = propagateUpdate(changedUrlInfo);
|
|
18502
|
+
const relativeUrl = formatUrlForClient(changedUrlInfo.url);
|
|
18503
|
+
if (hotUpdate.declined) {
|
|
18504
|
+
reloadMessage = {
|
|
18505
|
+
cause: `${relativeUrl} ${event}`,
|
|
18506
|
+
type: "full",
|
|
18507
|
+
typeReason: hotUpdate.reason,
|
|
18508
|
+
declinedBy: hotUpdate.declinedBy,
|
|
18509
|
+
};
|
|
18510
|
+
break;
|
|
18511
|
+
}
|
|
18512
|
+
const instructions = hotUpdate.instructions;
|
|
18513
|
+
if (reloadMessage) {
|
|
18514
|
+
reloadMessage.hotInstructions.push(...instructions);
|
|
18515
|
+
} else {
|
|
18516
|
+
reloadMessage = {
|
|
18517
|
+
cause: `${relativeUrl} ${event}`,
|
|
18518
|
+
type: "hot",
|
|
18519
|
+
typeReason: hotUpdate.reason,
|
|
18520
|
+
hot: changedUrlInfo.modifiedTimestamp,
|
|
18521
|
+
hotInstructions: instructions,
|
|
18522
|
+
};
|
|
18523
|
+
}
|
|
18524
|
+
continue;
|
|
18432
18525
|
}
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18526
|
+
|
|
18527
|
+
if (action.type === "prune") {
|
|
18528
|
+
const { prunedUrlInfo, lastReferenceFromOther } = action;
|
|
18529
|
+
if (lastReferenceFromOther.type === "sourcemap_comment") {
|
|
18530
|
+
// Can happen when starting dev server with sourcemaps: "file"
|
|
18531
|
+
// In that case, as sourcemaps are injected, the reference
|
|
18532
|
+
// are lost and sourcemap is considered as pruned
|
|
18533
|
+
continue;
|
|
18534
|
+
}
|
|
18535
|
+
const { ownerUrlInfo } = lastReferenceFromOther;
|
|
18536
|
+
if (!ownerUrlInfo.isUsed()) {
|
|
18537
|
+
continue;
|
|
18538
|
+
}
|
|
18539
|
+
const ownerHotUpdate = propagateUpdate(ownerUrlInfo);
|
|
18540
|
+
const cause = `${formatUrlForClient(
|
|
18541
|
+
prunedUrlInfo.url,
|
|
18542
|
+
)} is no longer referenced`;
|
|
18543
|
+
// now check if we can hot update the parent resource
|
|
18544
|
+
// then if we can hot update all dependencies
|
|
18545
|
+
if (ownerHotUpdate.declined) {
|
|
18546
|
+
reloadMessage = {
|
|
18547
|
+
cause,
|
|
18548
|
+
type: "full",
|
|
18549
|
+
typeReason: ownerHotUpdate.reason,
|
|
18550
|
+
declinedBy: ownerHotUpdate.declinedBy,
|
|
18551
|
+
};
|
|
18552
|
+
break;
|
|
18553
|
+
}
|
|
18554
|
+
// parent can hot update
|
|
18555
|
+
// but pruned url info declines
|
|
18556
|
+
if (prunedUrlInfo.data.hotDecline) {
|
|
18557
|
+
reloadMessage = {
|
|
18558
|
+
cause,
|
|
18559
|
+
type: "full",
|
|
18560
|
+
typeReason: `a pruned file declines hot reload`,
|
|
18561
|
+
declinedBy: formatUrlForClient(prunedUrlInfo.url),
|
|
18562
|
+
};
|
|
18563
|
+
break;
|
|
18564
|
+
}
|
|
18565
|
+
const pruneInstruction = {
|
|
18566
|
+
type: "prune",
|
|
18567
|
+
boundary: formatUrlForClient(prunedUrlInfo.url),
|
|
18568
|
+
acceptedBy: formatUrlForClient(
|
|
18569
|
+
lastReferenceFromOther.ownerUrlInfo.url,
|
|
18570
|
+
),
|
|
18571
|
+
};
|
|
18572
|
+
if (reloadMessage) {
|
|
18573
|
+
reloadMessage.hotInstructions.push(pruneInstruction);
|
|
18574
|
+
} else {
|
|
18575
|
+
reloadMessage = {
|
|
18576
|
+
cause,
|
|
18577
|
+
type: "hot",
|
|
18578
|
+
typeReason: ownerHotUpdate.reason,
|
|
18579
|
+
hot: prunedUrlInfo.prunedTimestamp,
|
|
18580
|
+
hotInstructions: [pruneInstruction],
|
|
18581
|
+
};
|
|
18436
18582
|
}
|
|
18437
18583
|
}
|
|
18438
18584
|
}
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
notifyFullReload({
|
|
18458
|
-
cause,
|
|
18459
|
-
reason: parentHotUpdate.reason,
|
|
18460
|
-
declinedBy: parentHotUpdate.declinedBy,
|
|
18461
|
-
});
|
|
18462
|
-
return;
|
|
18463
|
-
}
|
|
18464
|
-
// parent can hot update
|
|
18465
|
-
const instructions = [];
|
|
18466
|
-
if (prunedUrlInfo.data.hotDecline) {
|
|
18467
|
-
notifyFullReload({
|
|
18468
|
-
cause,
|
|
18469
|
-
reason: `a pruned file declines hot reload`,
|
|
18470
|
-
declinedBy: formatUrlForClient(prunedUrlInfo.url),
|
|
18585
|
+
if (reloadMessage) {
|
|
18586
|
+
serverEventInfo.sendServerEvent(reloadMessage);
|
|
18587
|
+
}
|
|
18588
|
+
};
|
|
18589
|
+
|
|
18590
|
+
clientFileChangeEventEmitter.on(({ url, event }) => {
|
|
18591
|
+
const changedUrlInfo = serverEventInfo.kitchen.graph.getUrlInfo(url);
|
|
18592
|
+
if (changedUrlInfo) {
|
|
18593
|
+
delayAction({
|
|
18594
|
+
type: "change",
|
|
18595
|
+
changedUrlInfo,
|
|
18596
|
+
event,
|
|
18597
|
+
});
|
|
18598
|
+
for (const searchParamVariant of changedUrlInfo.searchParamVariantSet) {
|
|
18599
|
+
delayAction({
|
|
18600
|
+
type: "change",
|
|
18601
|
+
changedUrlInfo: searchParamVariant,
|
|
18602
|
+
event,
|
|
18471
18603
|
});
|
|
18472
|
-
return;
|
|
18473
18604
|
}
|
|
18474
|
-
|
|
18605
|
+
}
|
|
18606
|
+
});
|
|
18607
|
+
clientFileDereferencedEventEmitter.on(
|
|
18608
|
+
(prunedUrlInfo, lastReferenceFromOther) => {
|
|
18609
|
+
delayAction({
|
|
18475
18610
|
type: "prune",
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
lastReferenceFromOther.ownerUrlInfo.url,
|
|
18479
|
-
),
|
|
18480
|
-
});
|
|
18481
|
-
notifyPartialReload({
|
|
18482
|
-
cause,
|
|
18483
|
-
reason: parentHotUpdate.reason,
|
|
18484
|
-
instructions,
|
|
18611
|
+
prunedUrlInfo,
|
|
18612
|
+
lastReferenceFromOther,
|
|
18485
18613
|
});
|
|
18486
18614
|
},
|
|
18487
18615
|
);
|
|
@@ -18507,15 +18635,15 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
18507
18635
|
};
|
|
18508
18636
|
|
|
18509
18637
|
const jsenvPluginAutoreload = ({
|
|
18510
|
-
|
|
18511
|
-
|
|
18638
|
+
clientFileChangeEventEmitter,
|
|
18639
|
+
clientFileDereferencedEventEmitter,
|
|
18512
18640
|
}) => {
|
|
18513
18641
|
return [
|
|
18514
18642
|
jsenvPluginHotSearchParam(),
|
|
18515
18643
|
jsenvPluginAutoreloadClient(),
|
|
18516
18644
|
jsenvPluginAutoreloadServer({
|
|
18517
|
-
|
|
18518
|
-
|
|
18645
|
+
clientFileChangeEventEmitter,
|
|
18646
|
+
clientFileDereferencedEventEmitter,
|
|
18519
18647
|
}),
|
|
18520
18648
|
];
|
|
18521
18649
|
};
|
|
@@ -18616,9 +18744,7 @@ const getCorePlugins = ({
|
|
|
18616
18744
|
transpilation = true,
|
|
18617
18745
|
inlining = true,
|
|
18618
18746
|
|
|
18619
|
-
clientAutoreload
|
|
18620
|
-
clientFileChangeCallbackList,
|
|
18621
|
-
clientFilesPruneCallbackList,
|
|
18747
|
+
clientAutoreload,
|
|
18622
18748
|
cacheControl,
|
|
18623
18749
|
scenarioPlaceholders = true,
|
|
18624
18750
|
ribbon = true,
|
|
@@ -18629,9 +18755,6 @@ const getCorePlugins = ({
|
|
|
18629
18755
|
if (supervisor === true) {
|
|
18630
18756
|
supervisor = {};
|
|
18631
18757
|
}
|
|
18632
|
-
if (clientAutoreload === true) {
|
|
18633
|
-
clientAutoreload = {};
|
|
18634
|
-
}
|
|
18635
18758
|
if (ribbon === true) {
|
|
18636
18759
|
ribbon = {};
|
|
18637
18760
|
}
|
|
@@ -18668,14 +18791,8 @@ const getCorePlugins = ({
|
|
|
18668
18791
|
jsenvPluginNodeRuntime({ runtimeCompat }),
|
|
18669
18792
|
|
|
18670
18793
|
jsenvPluginImportMetaHot(),
|
|
18671
|
-
...(clientAutoreload
|
|
18672
|
-
? [
|
|
18673
|
-
jsenvPluginAutoreload({
|
|
18674
|
-
...clientAutoreload,
|
|
18675
|
-
clientFileChangeCallbackList,
|
|
18676
|
-
clientFilesPruneCallbackList,
|
|
18677
|
-
}),
|
|
18678
|
-
]
|
|
18794
|
+
...(clientAutoreload && clientAutoreload.enabled
|
|
18795
|
+
? [jsenvPluginAutoreload(clientAutoreload)]
|
|
18679
18796
|
: []),
|
|
18680
18797
|
...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []),
|
|
18681
18798
|
...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
|
|
@@ -19189,63 +19306,60 @@ const createBuildVersionsManager = ({
|
|
|
19189
19306
|
|
|
19190
19307
|
const contentOnlyVersionMap = new Map();
|
|
19191
19308
|
{
|
|
19192
|
-
GRAPH_VISITOR.
|
|
19193
|
-
|
|
19194
|
-
|
|
19195
|
-
|
|
19196
|
-
|
|
19197
|
-
|
|
19198
|
-
|
|
19199
|
-
|
|
19200
|
-
|
|
19201
|
-
|
|
19202
|
-
|
|
19203
|
-
|
|
19204
|
-
|
|
19205
|
-
|
|
19206
|
-
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
|
|
19210
|
-
|
|
19211
|
-
|
|
19212
|
-
|
|
19213
|
-
|
|
19214
|
-
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
{
|
|
19229
|
-
cleanupJsenvAttributes: true,
|
|
19230
|
-
cleanupPositionAttributes: true,
|
|
19231
|
-
},
|
|
19232
|
-
);
|
|
19233
|
-
}
|
|
19234
|
-
if (
|
|
19235
|
-
CONTENT_TYPE.isTextual(urlInfo.contentType) &&
|
|
19236
|
-
urlInfo.referenceToOthersSet.size > 0
|
|
19237
|
-
) {
|
|
19238
|
-
const containedPlaceholders = new Set();
|
|
19239
|
-
const contentWithPredictibleVersionPlaceholders =
|
|
19240
|
-
replaceWithDefaultAndPopulateContainedPlaceholders(
|
|
19241
|
-
content,
|
|
19242
|
-
containedPlaceholders,
|
|
19309
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
19310
|
+
finalKitchen.graph.rootUrlInfo,
|
|
19311
|
+
(urlInfo) => {
|
|
19312
|
+
// ignore:
|
|
19313
|
+
// - inline files and data files:
|
|
19314
|
+
// they are already taken into account in the file where they appear
|
|
19315
|
+
// - ignored files:
|
|
19316
|
+
// we don't know their content
|
|
19317
|
+
// - unused files without reference
|
|
19318
|
+
// File updated such as style.css -> style.css.js or file.js->file.nomodule.js
|
|
19319
|
+
// Are used at some point just to be discarded later because they need to be converted
|
|
19320
|
+
// There is no need to version them and we could not because the file have been ignored
|
|
19321
|
+
// so their content is unknown
|
|
19322
|
+
if (urlInfo.type === "sourcemap") {
|
|
19323
|
+
return;
|
|
19324
|
+
}
|
|
19325
|
+
if (urlInfo.isInline) {
|
|
19326
|
+
return;
|
|
19327
|
+
}
|
|
19328
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
19329
|
+
// urlInfo became inline and is not referenced by something else
|
|
19330
|
+
return;
|
|
19331
|
+
}
|
|
19332
|
+
if (urlInfo.url.startsWith("ignore:")) {
|
|
19333
|
+
return;
|
|
19334
|
+
}
|
|
19335
|
+
let content = urlInfo.content;
|
|
19336
|
+
if (urlInfo.type === "html") {
|
|
19337
|
+
content = stringifyHtmlAst(
|
|
19338
|
+
parseHtmlString(urlInfo.content, {
|
|
19339
|
+
storeOriginalPositions: false,
|
|
19340
|
+
}),
|
|
19341
|
+
{
|
|
19342
|
+
cleanupJsenvAttributes: true,
|
|
19343
|
+
cleanupPositionAttributes: true,
|
|
19344
|
+
},
|
|
19243
19345
|
);
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
|
|
19248
|
-
|
|
19346
|
+
}
|
|
19347
|
+
if (
|
|
19348
|
+
CONTENT_TYPE.isTextual(urlInfo.contentType) &&
|
|
19349
|
+
urlInfo.referenceToOthersSet.size > 0
|
|
19350
|
+
) {
|
|
19351
|
+
const containedPlaceholders = new Set();
|
|
19352
|
+
const contentWithPredictibleVersionPlaceholders =
|
|
19353
|
+
replaceWithDefaultAndPopulateContainedPlaceholders(
|
|
19354
|
+
content,
|
|
19355
|
+
containedPlaceholders,
|
|
19356
|
+
);
|
|
19357
|
+
content = contentWithPredictibleVersionPlaceholders;
|
|
19358
|
+
}
|
|
19359
|
+
const contentVersion = generateVersion([content], versionLength);
|
|
19360
|
+
contentOnlyVersionMap.set(urlInfo, contentVersion);
|
|
19361
|
+
},
|
|
19362
|
+
);
|
|
19249
19363
|
}
|
|
19250
19364
|
|
|
19251
19365
|
{
|
|
@@ -19771,7 +19885,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
19771
19885
|
sourcemaps,
|
|
19772
19886
|
sourcemapsSourcesContent,
|
|
19773
19887
|
outDirectoryUrl: outDirectoryUrl
|
|
19774
|
-
? new URL("
|
|
19888
|
+
? new URL("prebuild/", outDirectoryUrl)
|
|
19775
19889
|
: undefined,
|
|
19776
19890
|
});
|
|
19777
19891
|
|
|
@@ -20026,13 +20140,6 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20026
20140
|
rawUrlInfo.url,
|
|
20027
20141
|
"raw file",
|
|
20028
20142
|
);
|
|
20029
|
-
if (buildUrl.includes("?")) {
|
|
20030
|
-
associateBuildUrlAndRawUrl(
|
|
20031
|
-
asUrlWithoutSearch(buildUrl),
|
|
20032
|
-
rawUrlInfo.url,
|
|
20033
|
-
"raw file",
|
|
20034
|
-
);
|
|
20035
|
-
}
|
|
20036
20143
|
return buildUrl;
|
|
20037
20144
|
}
|
|
20038
20145
|
if (reference.type === "sourcemap_comment") {
|
|
@@ -20246,82 +20353,84 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20246
20353
|
bundler.urlInfoMap.set(rawUrlInfo.url, rawUrlInfo);
|
|
20247
20354
|
}
|
|
20248
20355
|
};
|
|
20249
|
-
|
|
20250
|
-
|
|
20251
|
-
|
|
20252
|
-
|
|
20253
|
-
|
|
20254
|
-
|
|
20255
|
-
|
|
20256
|
-
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
}
|
|
20265
|
-
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
20266
|
-
if (referencedUrlInfo.isInline) {
|
|
20267
|
-
if (referencedUrlInfo.type === "js_module") {
|
|
20268
|
-
// bundle inline script type module deps
|
|
20269
|
-
referencedUrlInfo.referenceToOthersSet.forEach(
|
|
20270
|
-
(jsModuleReferenceToOther) => {
|
|
20271
|
-
if (jsModuleReferenceToOther.type === "js_import") {
|
|
20272
|
-
const inlineUrlInfo = jsModuleReferenceToOther.urlInfo;
|
|
20273
|
-
addToBundlerIfAny(inlineUrlInfo);
|
|
20274
|
-
}
|
|
20275
|
-
},
|
|
20276
|
-
);
|
|
20356
|
+
// ignore unused urls thanks to "forEachUrlInfoStronglyReferenced"
|
|
20357
|
+
// it avoid bundling things that are not actually used
|
|
20358
|
+
// happens for:
|
|
20359
|
+
// - js import assertions
|
|
20360
|
+
// - conversion to js classic using ?as_js_classic or ?js_module_fallback
|
|
20361
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
20362
|
+
rawKitchen.graph.rootUrlInfo,
|
|
20363
|
+
(rawUrlInfo) => {
|
|
20364
|
+
if (rawUrlInfo.isEntryPoint) {
|
|
20365
|
+
addToBundlerIfAny(rawUrlInfo);
|
|
20366
|
+
}
|
|
20367
|
+
if (rawUrlInfo.type === "html") {
|
|
20368
|
+
rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
20369
|
+
if (referenceToOther.isWeak) {
|
|
20370
|
+
return;
|
|
20277
20371
|
}
|
|
20278
|
-
// inline content cannot be bundled
|
|
20279
|
-
return;
|
|
20280
|
-
}
|
|
20281
|
-
addToBundlerIfAny(referencedUrlInfo);
|
|
20282
|
-
});
|
|
20283
|
-
rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
20284
|
-
if (
|
|
20285
|
-
referenceToOther.isResourceHint &&
|
|
20286
|
-
referenceToOther.expectedType === "js_module"
|
|
20287
|
-
) {
|
|
20288
20372
|
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
20373
|
+
if (referencedUrlInfo.isInline) {
|
|
20374
|
+
if (referencedUrlInfo.type === "js_module") {
|
|
20375
|
+
// bundle inline script type module deps
|
|
20376
|
+
referencedUrlInfo.referenceToOthersSet.forEach(
|
|
20377
|
+
(jsModuleReferenceToOther) => {
|
|
20378
|
+
if (jsModuleReferenceToOther.type === "js_import") {
|
|
20379
|
+
const inlineUrlInfo =
|
|
20380
|
+
jsModuleReferenceToOther.urlInfo;
|
|
20381
|
+
addToBundlerIfAny(inlineUrlInfo);
|
|
20382
|
+
}
|
|
20383
|
+
},
|
|
20384
|
+
);
|
|
20385
|
+
}
|
|
20386
|
+
// inline content cannot be bundled
|
|
20387
|
+
return;
|
|
20388
|
+
}
|
|
20389
|
+
addToBundlerIfAny(referencedUrlInfo);
|
|
20390
|
+
});
|
|
20391
|
+
rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
20289
20392
|
if (
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
referencedUrlInfo.referenceFromOthersSet.size > 0
|
|
20393
|
+
referenceToOther.isResourceHint &&
|
|
20394
|
+
referenceToOther.expectedType === "js_module"
|
|
20293
20395
|
) {
|
|
20294
|
-
|
|
20396
|
+
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
20397
|
+
if (
|
|
20398
|
+
referencedUrlInfo &&
|
|
20399
|
+
// something else than the resource hint is using this url
|
|
20400
|
+
referencedUrlInfo.referenceFromOthersSet.size > 0
|
|
20401
|
+
) {
|
|
20402
|
+
addToBundlerIfAny(referencedUrlInfo);
|
|
20403
|
+
}
|
|
20295
20404
|
}
|
|
20296
|
-
}
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
|
|
20306
|
-
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
|
|
20405
|
+
});
|
|
20406
|
+
return;
|
|
20407
|
+
}
|
|
20408
|
+
// File referenced with new URL('./file.js', import.meta.url)
|
|
20409
|
+
// are entry points that should be bundled
|
|
20410
|
+
// For instance we will bundle service worker/workers detected like this
|
|
20411
|
+
if (rawUrlInfo.type === "js_module") {
|
|
20412
|
+
rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
|
|
20413
|
+
if (referenceToOther.type === "js_url") {
|
|
20414
|
+
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
20415
|
+
for (const referenceFromOther of referencedUrlInfo.referenceFromOthersSet) {
|
|
20416
|
+
if (referenceFromOther.url === referencedUrlInfo.url) {
|
|
20417
|
+
if (
|
|
20418
|
+
referenceFromOther.subtype === "import_dynamic" ||
|
|
20419
|
+
referenceFromOther.type === "script"
|
|
20420
|
+
) {
|
|
20421
|
+
// will already be bundled
|
|
20422
|
+
return;
|
|
20423
|
+
}
|
|
20315
20424
|
}
|
|
20316
20425
|
}
|
|
20426
|
+
addToBundlerIfAny(referencedUrlInfo);
|
|
20427
|
+
return;
|
|
20317
20428
|
}
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
}
|
|
20324
|
-
});
|
|
20429
|
+
if (referenceToOther.type === "js_inline_content") ;
|
|
20430
|
+
});
|
|
20431
|
+
}
|
|
20432
|
+
},
|
|
20433
|
+
);
|
|
20325
20434
|
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
20326
20435
|
await previous;
|
|
20327
20436
|
const bundler = bundlers[type];
|
|
@@ -20631,24 +20740,14 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20631
20740
|
resyncTask.done();
|
|
20632
20741
|
}
|
|
20633
20742
|
}
|
|
20634
|
-
{
|
|
20635
|
-
const actions = [];
|
|
20636
|
-
GRAPH_VISITOR.forEach(finalKitchen.graph, (urlInfo) => {
|
|
20637
|
-
if (!urlInfo.isUsed()) {
|
|
20638
|
-
actions.push(() => {
|
|
20639
|
-
urlInfo.deleteFromGraph();
|
|
20640
|
-
});
|
|
20641
|
-
}
|
|
20642
|
-
});
|
|
20643
|
-
actions.forEach((action) => action());
|
|
20644
|
-
}
|
|
20645
20743
|
{
|
|
20646
20744
|
const serviceWorkerEntryUrlInfos = GRAPH_VISITOR.filter(
|
|
20647
20745
|
finalKitchen.graph,
|
|
20648
20746
|
(finalUrlInfo) => {
|
|
20649
20747
|
return (
|
|
20650
20748
|
finalUrlInfo.subtype === "service_worker" &&
|
|
20651
|
-
finalUrlInfo.isEntryPoint
|
|
20749
|
+
finalUrlInfo.isEntryPoint &&
|
|
20750
|
+
finalUrlInfo.isUsed()
|
|
20652
20751
|
);
|
|
20653
20752
|
},
|
|
20654
20753
|
);
|
|
@@ -20657,34 +20756,34 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20657
20756
|
"inject urls in service worker",
|
|
20658
20757
|
);
|
|
20659
20758
|
const serviceWorkerResources = {};
|
|
20660
|
-
GRAPH_VISITOR.
|
|
20661
|
-
|
|
20662
|
-
|
|
20663
|
-
|
|
20664
|
-
|
|
20665
|
-
|
|
20666
|
-
|
|
20667
|
-
|
|
20668
|
-
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20759
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
20760
|
+
finalKitchen.graph.rootUrlInfo,
|
|
20761
|
+
(urlInfo) => {
|
|
20762
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
20763
|
+
return;
|
|
20764
|
+
}
|
|
20765
|
+
if (urlInfo.isInline) {
|
|
20766
|
+
return;
|
|
20767
|
+
}
|
|
20768
|
+
if (!canUseVersionedUrl(urlInfo)) {
|
|
20769
|
+
// when url is not versioned we compute a "version" for that url anyway
|
|
20770
|
+
// so that service worker source still changes and navigator
|
|
20771
|
+
// detect there is a change
|
|
20772
|
+
const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
|
|
20773
|
+
serviceWorkerResources[buildSpecifier] = {
|
|
20774
|
+
version: buildVersionsManager.getVersion(urlInfo),
|
|
20775
|
+
};
|
|
20776
|
+
return;
|
|
20777
|
+
}
|
|
20674
20778
|
const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
|
|
20779
|
+
const buildSpecifierVersioned =
|
|
20780
|
+
buildVersionsManager.getBuildSpecifierVersioned(buildSpecifier);
|
|
20675
20781
|
serviceWorkerResources[buildSpecifier] = {
|
|
20676
20782
|
version: buildVersionsManager.getVersion(urlInfo),
|
|
20783
|
+
versionedUrl: buildSpecifierVersioned,
|
|
20677
20784
|
};
|
|
20678
|
-
|
|
20679
|
-
|
|
20680
|
-
const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
|
|
20681
|
-
const buildSpecifierVersioned =
|
|
20682
|
-
buildVersionsManager.getBuildSpecifierVersioned(buildSpecifier);
|
|
20683
|
-
serviceWorkerResources[buildSpecifier] = {
|
|
20684
|
-
version: buildVersionsManager.getVersion(urlInfo),
|
|
20685
|
-
versionedUrl: buildSpecifierVersioned,
|
|
20686
|
-
};
|
|
20687
|
-
});
|
|
20785
|
+
},
|
|
20786
|
+
);
|
|
20688
20787
|
for (const serviceWorkerEntryUrlInfo of serviceWorkerEntryUrlInfos) {
|
|
20689
20788
|
const serviceWorkerResourcesWithoutSwScriptItSelf = {
|
|
20690
20789
|
...serviceWorkerResources,
|
|
@@ -20724,48 +20823,48 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20724
20823
|
const buildRelativeUrl = urlToRelativeUrl(url, buildDirectoryUrl);
|
|
20725
20824
|
return buildRelativeUrl;
|
|
20726
20825
|
};
|
|
20727
|
-
GRAPH_VISITOR.
|
|
20728
|
-
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20743
|
-
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20750
|
-
|
|
20751
|
-
|
|
20752
|
-
|
|
20753
|
-
|
|
20754
|
-
|
|
20755
|
-
|
|
20756
|
-
|
|
20757
|
-
|
|
20758
|
-
|
|
20759
|
-
|
|
20826
|
+
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
20827
|
+
finalKitchen.graph.rootUrlInfo,
|
|
20828
|
+
(urlInfo) => {
|
|
20829
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
20830
|
+
return;
|
|
20831
|
+
}
|
|
20832
|
+
if (urlInfo.type === "directory") {
|
|
20833
|
+
return;
|
|
20834
|
+
}
|
|
20835
|
+
if (urlInfo.isInline) {
|
|
20836
|
+
const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
|
|
20837
|
+
buildContents[buildRelativeUrl] = urlInfo.content;
|
|
20838
|
+
buildInlineRelativeUrls.push(buildRelativeUrl);
|
|
20839
|
+
} else {
|
|
20840
|
+
const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
|
|
20841
|
+
if (
|
|
20842
|
+
buildVersionsManager.getVersion(urlInfo) &&
|
|
20843
|
+
canUseVersionedUrl(urlInfo)
|
|
20844
|
+
) {
|
|
20845
|
+
const buildSpecifier = findKey(buildSpecifierMap, urlInfo.url);
|
|
20846
|
+
const buildSpecifierVersioned =
|
|
20847
|
+
buildVersionsManager.getBuildSpecifierVersioned(buildSpecifier);
|
|
20848
|
+
const buildUrlVersioned = asBuildUrlVersioned({
|
|
20849
|
+
buildSpecifierVersioned,
|
|
20850
|
+
buildDirectoryUrl,
|
|
20851
|
+
});
|
|
20852
|
+
const buildRelativeUrlVersioned = urlToRelativeUrl(
|
|
20853
|
+
buildUrlVersioned,
|
|
20854
|
+
buildDirectoryUrl,
|
|
20855
|
+
);
|
|
20856
|
+
if (versioningMethod === "search_param") {
|
|
20857
|
+
buildContents[buildRelativeUrl] = urlInfo.content;
|
|
20858
|
+
} else {
|
|
20859
|
+
buildContents[buildRelativeUrlVersioned] = urlInfo.content;
|
|
20860
|
+
}
|
|
20861
|
+
buildManifest[buildRelativeUrl] = buildRelativeUrlVersioned;
|
|
20760
20862
|
} else {
|
|
20761
|
-
buildContents[
|
|
20863
|
+
buildContents[buildRelativeUrl] = urlInfo.content;
|
|
20762
20864
|
}
|
|
20763
|
-
buildManifest[buildRelativeUrl] = buildRelativeUrlVersioned;
|
|
20764
|
-
} else {
|
|
20765
|
-
buildContents[buildRelativeUrl] = urlInfo.content;
|
|
20766
20865
|
}
|
|
20767
|
-
}
|
|
20768
|
-
|
|
20866
|
+
},
|
|
20867
|
+
);
|
|
20769
20868
|
const buildFileContents = {};
|
|
20770
20869
|
const buildInlineContents = {};
|
|
20771
20870
|
Object.keys(buildContents)
|
|
@@ -20800,7 +20899,9 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20800
20899
|
writingFiles.done();
|
|
20801
20900
|
}
|
|
20802
20901
|
logger.info(
|
|
20803
|
-
createUrlGraphSummary(finalKitchen.graph, {
|
|
20902
|
+
createUrlGraphSummary(finalKitchen.graph, {
|
|
20903
|
+
title: "build files",
|
|
20904
|
+
}),
|
|
20804
20905
|
);
|
|
20805
20906
|
return {
|
|
20806
20907
|
buildFileContents,
|
|
@@ -21020,6 +21121,7 @@ const createFileService = ({
|
|
|
21020
21121
|
serverStopCallbacks,
|
|
21021
21122
|
serverEventsDispatcher,
|
|
21022
21123
|
kitchenCache,
|
|
21124
|
+
onKitchenCreated = () => {},
|
|
21023
21125
|
|
|
21024
21126
|
sourceDirectoryUrl,
|
|
21025
21127
|
sourceMainFilePath,
|
|
@@ -21035,8 +21137,6 @@ const createFileService = ({
|
|
|
21035
21137
|
supervisor,
|
|
21036
21138
|
transpilation,
|
|
21037
21139
|
clientAutoreload,
|
|
21038
|
-
cooldownBetweenFileEvents,
|
|
21039
|
-
clientServerEventsConfig,
|
|
21040
21140
|
cacheControl,
|
|
21041
21141
|
ribbon,
|
|
21042
21142
|
sourcemaps,
|
|
@@ -21044,19 +21144,32 @@ const createFileService = ({
|
|
|
21044
21144
|
sourcemapsSourcesContent,
|
|
21045
21145
|
outDirectoryUrl,
|
|
21046
21146
|
}) => {
|
|
21047
|
-
|
|
21048
|
-
|
|
21147
|
+
if (clientAutoreload === true) {
|
|
21148
|
+
clientAutoreload = {};
|
|
21149
|
+
}
|
|
21150
|
+
if (clientAutoreload === false) {
|
|
21151
|
+
clientAutoreload = { enabled: false };
|
|
21152
|
+
}
|
|
21153
|
+
const clientFileChangeEventEmitter = createEventEmitter();
|
|
21154
|
+
const clientFileDereferencedEventEmitter = createEventEmitter();
|
|
21155
|
+
|
|
21156
|
+
clientAutoreload = {
|
|
21157
|
+
enabled: true,
|
|
21158
|
+
clientServerEventsConfig: {},
|
|
21159
|
+
clientFileChangeEventEmitter,
|
|
21160
|
+
clientFileDereferencedEventEmitter,
|
|
21161
|
+
...clientAutoreload,
|
|
21162
|
+
};
|
|
21163
|
+
|
|
21049
21164
|
const stopWatchingSourceFiles = watchSourceFiles(
|
|
21050
21165
|
sourceDirectoryUrl,
|
|
21051
21166
|
(fileInfo) => {
|
|
21052
|
-
|
|
21053
|
-
callback(fileInfo);
|
|
21054
|
-
});
|
|
21167
|
+
clientFileChangeEventEmitter.emit(fileInfo);
|
|
21055
21168
|
},
|
|
21056
21169
|
{
|
|
21057
21170
|
sourceFilesConfig,
|
|
21058
21171
|
keepProcessAlive: false,
|
|
21059
|
-
cooldownBetweenFileEvents,
|
|
21172
|
+
cooldownBetweenFileEvents: clientAutoreload.cooldownBetweenFileEvents,
|
|
21060
21173
|
},
|
|
21061
21174
|
);
|
|
21062
21175
|
serverStopCallbacks.push(stopWatchingSourceFiles);
|
|
@@ -21075,10 +21188,10 @@ const createFileService = ({
|
|
|
21075
21188
|
sourceDirectoryUrl,
|
|
21076
21189
|
);
|
|
21077
21190
|
let kitchen;
|
|
21078
|
-
|
|
21191
|
+
clientFileChangeEventEmitter.on(({ url }) => {
|
|
21079
21192
|
const urlInfo = kitchen.graph.getUrlInfo(url);
|
|
21080
21193
|
if (urlInfo) {
|
|
21081
|
-
urlInfo.
|
|
21194
|
+
urlInfo.onModified();
|
|
21082
21195
|
}
|
|
21083
21196
|
});
|
|
21084
21197
|
const clientRuntimeCompat = { [runtimeName]: runtimeVersion };
|
|
@@ -21114,8 +21227,6 @@ const createFileService = ({
|
|
|
21114
21227
|
transpilation,
|
|
21115
21228
|
|
|
21116
21229
|
clientAutoreload,
|
|
21117
|
-
clientFileChangeCallbackList,
|
|
21118
|
-
clientFilesPruneCallbackList,
|
|
21119
21230
|
cacheControl,
|
|
21120
21231
|
ribbon,
|
|
21121
21232
|
}),
|
|
@@ -21129,18 +21240,18 @@ const createFileService = ({
|
|
|
21129
21240
|
? new URL(`${runtimeName}@${runtimeVersion}/`, outDirectoryUrl)
|
|
21130
21241
|
: undefined,
|
|
21131
21242
|
});
|
|
21132
|
-
kitchen.graph.
|
|
21243
|
+
kitchen.graph.urlInfoCreatedEventEmitter.on((urlInfoCreated) => {
|
|
21133
21244
|
const { watch } = URL_META.applyAssociations({
|
|
21134
|
-
url:
|
|
21245
|
+
url: urlInfoCreated.url,
|
|
21135
21246
|
associations: watchAssociations,
|
|
21136
21247
|
});
|
|
21137
|
-
|
|
21248
|
+
urlInfoCreated.isWatched = watch;
|
|
21138
21249
|
// wehn an url depends on many others, we check all these (like package.json)
|
|
21139
|
-
|
|
21140
|
-
if (!
|
|
21250
|
+
urlInfoCreated.isValid = () => {
|
|
21251
|
+
if (!urlInfoCreated.url.startsWith("file:")) {
|
|
21141
21252
|
return false;
|
|
21142
21253
|
}
|
|
21143
|
-
if (
|
|
21254
|
+
if (urlInfoCreated.content === undefined) {
|
|
21144
21255
|
// urlInfo content is undefined when:
|
|
21145
21256
|
// - url info content never fetched
|
|
21146
21257
|
// - it is considered as modified because undelying file is watched and got saved
|
|
@@ -21152,21 +21263,20 @@ const createFileService = ({
|
|
|
21152
21263
|
// file is not watched, check the filesystem
|
|
21153
21264
|
let fileContentAsBuffer;
|
|
21154
21265
|
try {
|
|
21155
|
-
fileContentAsBuffer = readFileSync(new URL(
|
|
21266
|
+
fileContentAsBuffer = readFileSync(new URL(urlInfoCreated.url));
|
|
21156
21267
|
} catch (e) {
|
|
21157
21268
|
if (e.code === "ENOENT") {
|
|
21158
|
-
|
|
21159
|
-
urlInfo.deleteFromGraph();
|
|
21269
|
+
urlInfoCreated.onModified();
|
|
21160
21270
|
return false;
|
|
21161
21271
|
}
|
|
21162
21272
|
return false;
|
|
21163
21273
|
}
|
|
21164
21274
|
const fileContentEtag = bufferToEtag$1(fileContentAsBuffer);
|
|
21165
|
-
if (fileContentEtag !==
|
|
21166
|
-
|
|
21275
|
+
if (fileContentEtag !== urlInfoCreated.originalContentEtag) {
|
|
21276
|
+
urlInfoCreated.onModified();
|
|
21167
21277
|
// restore content to be able to compare it again later
|
|
21168
|
-
|
|
21169
|
-
|
|
21278
|
+
urlInfoCreated.kitchen.urlInfoTransformer.setContent(
|
|
21279
|
+
urlInfoCreated,
|
|
21170
21280
|
String(fileContentAsBuffer),
|
|
21171
21281
|
{
|
|
21172
21282
|
contentEtag: fileContentEtag,
|
|
@@ -21175,23 +21285,24 @@ const createFileService = ({
|
|
|
21175
21285
|
return false;
|
|
21176
21286
|
}
|
|
21177
21287
|
}
|
|
21178
|
-
for (const implicitUrl of
|
|
21179
|
-
const implicitUrlInfo =
|
|
21288
|
+
for (const implicitUrl of urlInfoCreated.implicitUrlSet) {
|
|
21289
|
+
const implicitUrlInfo = urlInfoCreated.graph.getUrlInfo(implicitUrl);
|
|
21180
21290
|
if (implicitUrlInfo && !implicitUrlInfo.isValid()) {
|
|
21181
21291
|
return false;
|
|
21182
21292
|
}
|
|
21183
21293
|
}
|
|
21184
21294
|
return true;
|
|
21185
21295
|
};
|
|
21186
|
-
};
|
|
21187
|
-
kitchen.graph.
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
}
|
|
21194
|
-
|
|
21296
|
+
});
|
|
21297
|
+
kitchen.graph.urlInfoDereferencedEventEmitter.on(
|
|
21298
|
+
(urlInfoDereferenced, lastReferenceFromOther) => {
|
|
21299
|
+
clientFileDereferencedEventEmitter.emit(
|
|
21300
|
+
urlInfoDereferenced,
|
|
21301
|
+
lastReferenceFromOther,
|
|
21302
|
+
);
|
|
21303
|
+
},
|
|
21304
|
+
);
|
|
21305
|
+
|
|
21195
21306
|
serverStopCallbacks.push(() => {
|
|
21196
21307
|
kitchen.pluginController.callHooks("destroy", kitchen.context);
|
|
21197
21308
|
});
|
|
@@ -21224,12 +21335,15 @@ const createFileService = ({
|
|
|
21224
21335
|
});
|
|
21225
21336
|
// "pushPlugin" so that event source client connection can be put as early as possible in html
|
|
21226
21337
|
kitchen.pluginController.pushPlugin(
|
|
21227
|
-
jsenvPluginServerEventsClientInjection(
|
|
21338
|
+
jsenvPluginServerEventsClientInjection(
|
|
21339
|
+
clientAutoreload.clientServerEventsConfig,
|
|
21340
|
+
),
|
|
21228
21341
|
);
|
|
21229
21342
|
}
|
|
21230
21343
|
}
|
|
21231
21344
|
|
|
21232
21345
|
kitchenCache.set(runtimeId, kitchen);
|
|
21346
|
+
onKitchenCreated(kitchen);
|
|
21233
21347
|
return kitchen;
|
|
21234
21348
|
};
|
|
21235
21349
|
|
|
@@ -21247,31 +21361,28 @@ const createFileService = ({
|
|
|
21247
21361
|
if (responseFromPlugin) {
|
|
21248
21362
|
return responseFromPlugin;
|
|
21249
21363
|
}
|
|
21250
|
-
|
|
21251
|
-
const parentUrl =
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
|
|
21364
|
+
const { referer } = request.headers;
|
|
21365
|
+
const parentUrl = referer
|
|
21366
|
+
? WEB_URL_CONVERTER.asFileUrl(referer, {
|
|
21367
|
+
origin: request.origin,
|
|
21368
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
21369
|
+
})
|
|
21370
|
+
: sourceDirectoryUrl;
|
|
21371
|
+
let reference = kitchen.graph.inferReference(request.resource, parentUrl);
|
|
21255
21372
|
if (!reference) {
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
}
|
|
21263
|
-
reference = parentUrlInfo.dependencies.createResolveAndFinalize({
|
|
21264
|
-
trace: { message: parentUrl || sourceDirectoryUrl },
|
|
21265
|
-
type: "http_request",
|
|
21266
|
-
specifier: request.resource,
|
|
21267
|
-
});
|
|
21373
|
+
reference =
|
|
21374
|
+
kitchen.graph.rootUrlInfo.dependencies.createResolveAndFinalize({
|
|
21375
|
+
trace: { message: parentUrl },
|
|
21376
|
+
type: "http_request",
|
|
21377
|
+
specifier: request.resource,
|
|
21378
|
+
});
|
|
21268
21379
|
}
|
|
21269
21380
|
const urlInfo = reference.urlInfo;
|
|
21270
21381
|
const ifNoneMatch = request.headers["if-none-match"];
|
|
21271
21382
|
const urlInfoTargetedByCache = urlInfo.findParentIfInline() || urlInfo;
|
|
21272
21383
|
|
|
21273
21384
|
try {
|
|
21274
|
-
if (ifNoneMatch) {
|
|
21385
|
+
if (!urlInfo.error && ifNoneMatch) {
|
|
21275
21386
|
const [clientOriginalContentEtag, clientContentEtag] =
|
|
21276
21387
|
ifNoneMatch.split("_");
|
|
21277
21388
|
if (
|
|
@@ -21319,7 +21430,7 @@ const createFileService = ({
|
|
|
21319
21430
|
}),
|
|
21320
21431
|
...urlInfo.headers,
|
|
21321
21432
|
"content-type": urlInfo.contentType,
|
|
21322
|
-
"content-length":
|
|
21433
|
+
"content-length": urlInfo.contentLength,
|
|
21323
21434
|
},
|
|
21324
21435
|
body: urlInfo.content,
|
|
21325
21436
|
timing: urlInfo.timing,
|
|
@@ -21358,7 +21469,7 @@ const createFileService = ({
|
|
|
21358
21469
|
statusMessage: originalError.message,
|
|
21359
21470
|
headers: {
|
|
21360
21471
|
"content-type": urlInfo.contentType,
|
|
21361
|
-
"content-length":
|
|
21472
|
+
"content-length": urlInfo.contentLength,
|
|
21362
21473
|
"cache-control": "no-store",
|
|
21363
21474
|
},
|
|
21364
21475
|
body: urlInfo.content,
|
|
@@ -21405,30 +21516,10 @@ const createFileService = ({
|
|
|
21405
21516
|
statusText: e.reason,
|
|
21406
21517
|
statusMessage: e.stack,
|
|
21407
21518
|
};
|
|
21408
|
-
} finally {
|
|
21409
|
-
// remove http_request when there is other references keeping url info alive
|
|
21410
|
-
if (
|
|
21411
|
-
reference.type === "http_request" &&
|
|
21412
|
-
reference.urlInfo.referenceFromOthersSet.size > 1
|
|
21413
|
-
) {
|
|
21414
|
-
reference.remove();
|
|
21415
|
-
}
|
|
21416
21519
|
}
|
|
21417
21520
|
};
|
|
21418
21521
|
};
|
|
21419
21522
|
|
|
21420
|
-
const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
21421
|
-
const { referer } = request.headers;
|
|
21422
|
-
if (!referer) {
|
|
21423
|
-
return null;
|
|
21424
|
-
}
|
|
21425
|
-
const refererUrl = referer;
|
|
21426
|
-
return WEB_URL_CONVERTER.asFileUrl(refererUrl, {
|
|
21427
|
-
origin: request.origin,
|
|
21428
|
-
rootDirectoryUrl: sourceDirectoryUrl,
|
|
21429
|
-
});
|
|
21430
|
-
};
|
|
21431
|
-
|
|
21432
21523
|
/**
|
|
21433
21524
|
* Start a server for source files:
|
|
21434
21525
|
* - cook source files according to jsenv plugins
|
|
@@ -21459,8 +21550,6 @@ const startDevServer = async ({
|
|
|
21459
21550
|
|
|
21460
21551
|
sourceFilesConfig,
|
|
21461
21552
|
clientAutoreload = true,
|
|
21462
|
-
cooldownBetweenFileEvents,
|
|
21463
|
-
clientServerEventsConfig = {},
|
|
21464
21553
|
|
|
21465
21554
|
// runtimeCompat is the runtimeCompat for the build
|
|
21466
21555
|
// when specified, dev server use it to warn in case
|
|
@@ -21476,6 +21565,7 @@ const startDevServer = async ({
|
|
|
21476
21565
|
cacheControl = true,
|
|
21477
21566
|
ribbon = true,
|
|
21478
21567
|
// toolbar = false,
|
|
21568
|
+
onKitchenCreated = () => {},
|
|
21479
21569
|
|
|
21480
21570
|
sourcemaps = "inline",
|
|
21481
21571
|
sourcemapsSourcesProtocol,
|
|
@@ -21600,6 +21690,7 @@ const startDevServer = async ({
|
|
|
21600
21690
|
serverStopCallbacks,
|
|
21601
21691
|
serverEventsDispatcher,
|
|
21602
21692
|
kitchenCache,
|
|
21693
|
+
onKitchenCreated,
|
|
21603
21694
|
|
|
21604
21695
|
sourceDirectoryUrl,
|
|
21605
21696
|
sourceMainFilePath,
|
|
@@ -21615,8 +21706,6 @@ const startDevServer = async ({
|
|
|
21615
21706
|
supervisor,
|
|
21616
21707
|
transpilation,
|
|
21617
21708
|
clientAutoreload,
|
|
21618
|
-
cooldownBetweenFileEvents,
|
|
21619
|
-
clientServerEventsConfig,
|
|
21620
21709
|
cacheControl,
|
|
21621
21710
|
ribbon,
|
|
21622
21711
|
sourcemaps,
|