@jsenv/core 41.4.5 → 41.4.7
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/build/build.js +202 -117
- package/dist/start_dev_server/start_dev_server.js +111 -52
- package/package.json +1 -1
- package/src/build/build.js +6 -18
- package/src/build/build_specifier_manager.js +49 -21
- package/src/build/build_urls_generator.js +43 -22
- package/src/dev/dev_server_plugins/dev_server_plugin_serve_source_files.js +10 -1
- package/src/helpers/bare_specifier.js +18 -0
- package/src/kitchen/errors.js +5 -4
- package/src/kitchen/url_graph/url_graph.js +3 -0
- package/src/kitchen/url_graph/url_info_injections.js +11 -4
- package/src/plugins/injections/jsenv_plugin_injections.js +53 -6
- package/src/plugins/plugins.js +3 -1
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +1 -17
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +1 -17
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +7 -1
package/dist/build/build.js
CHANGED
|
@@ -628,9 +628,10 @@ const getFirstReferenceInProject = (reference) => {
|
|
|
628
628
|
return getFirstReferenceInProject(firstReference);
|
|
629
629
|
};
|
|
630
630
|
|
|
631
|
-
//
|
|
632
|
-
//
|
|
633
|
-
// (the key is free-form), tell the file it comes
|
|
631
|
+
// Injections write urls in html attributes before references are analyzed, so an url
|
|
632
|
+
// that still cannot be resolved may be a placeholder no injection replaced. Rather than
|
|
633
|
+
// guessing what a placeholder looks like (the key is free-form), tell the file it comes
|
|
634
|
+
// from: injections are configured for it.
|
|
634
635
|
const detailsFromInjectionsOnOwner = (reference) => {
|
|
635
636
|
if (!reference) {
|
|
636
637
|
return {};
|
|
@@ -649,7 +650,7 @@ const detailsFromInjectionsOnOwner = (reference) => {
|
|
|
649
650
|
return {};
|
|
650
651
|
}
|
|
651
652
|
return {
|
|
652
|
-
suggestion: `injections are configured for this file; when "${reference.specifier}" is meant to be written by one of them, add "jsenv-ignore" so jsenv leaves that url alone:
|
|
653
|
+
suggestion: `injections are configured for this file; when "${reference.specifier}" is meant to be written by one of them, check the placeholder spelling, or add "jsenv-ignore" so jsenv leaves that url alone:
|
|
653
654
|
<${node.nodeName} jsenv-ignore ${attributeName}="${reference.specifier}" />`,
|
|
654
655
|
};
|
|
655
656
|
};
|
|
@@ -2101,6 +2102,9 @@ const createUrlInfo = (url, context) => {
|
|
|
2101
2102
|
contentFinalized: false,
|
|
2102
2103
|
contentSideEffects: [],
|
|
2103
2104
|
contentInjections: {},
|
|
2105
|
+
// placeholders already consumed somewhere else than the content (in a specifier),
|
|
2106
|
+
// so that not finding them in the content is not worth a warning
|
|
2107
|
+
contentInjectionUsedKeySet: new Set(),
|
|
2104
2108
|
|
|
2105
2109
|
sourcemap: null,
|
|
2106
2110
|
sourcemapIsWrong: false,
|
|
@@ -2413,6 +2417,13 @@ const INJECTIONS = {
|
|
|
2413
2417
|
},
|
|
2414
2418
|
};
|
|
2415
2419
|
|
|
2420
|
+
const readInjectionValue = (injection) => {
|
|
2421
|
+
if (injection && injection[injectionSymbol]) {
|
|
2422
|
+
return injection.value;
|
|
2423
|
+
}
|
|
2424
|
+
return injection;
|
|
2425
|
+
};
|
|
2426
|
+
|
|
2416
2427
|
const isPlaceholderInjection = (value) => {
|
|
2417
2428
|
return (
|
|
2418
2429
|
!value || !value[injectionSymbol] || value[injectionSymbol] !== "global"
|
|
@@ -2486,7 +2497,7 @@ const injectPlaceholderReplacements = (
|
|
|
2486
2497
|
for (const { key, isOptional, value } of placeholderReplacements) {
|
|
2487
2498
|
let index = content.indexOf(key);
|
|
2488
2499
|
if (index === -1) {
|
|
2489
|
-
if (!isOptional) {
|
|
2500
|
+
if (!isOptional && !urlInfo.contentInjectionUsedKeySet.has(key)) {
|
|
2490
2501
|
urlInfo.context.logger.warn(
|
|
2491
2502
|
`placeholder "${key}" not found in ${urlInfo.url}.
|
|
2492
2503
|
--- suggestion a ---
|
|
@@ -2511,7 +2522,7 @@ return {
|
|
|
2511
2522
|
magicSource.replace({
|
|
2512
2523
|
start,
|
|
2513
2524
|
end,
|
|
2514
|
-
replacement: asReplacement(value, urlInfo),
|
|
2525
|
+
replacement: asReplacement(value, urlInfo.type),
|
|
2515
2526
|
});
|
|
2516
2527
|
index = content.indexOf(key, end);
|
|
2517
2528
|
}
|
|
@@ -2522,8 +2533,8 @@ return {
|
|
|
2522
2533
|
// In JS the placeholder stands for a value, so it must be substituted by a literal.
|
|
2523
2534
|
// Everywhere else (html attributes and text, css, ...) it stands for a piece of text
|
|
2524
2535
|
// and is substituted as-is, so it can be concatenated: href="__BACKEND_URL__/users/me"
|
|
2525
|
-
const asReplacement = (value,
|
|
2526
|
-
if (
|
|
2536
|
+
const asReplacement = (value, type) => {
|
|
2537
|
+
if (type === "js_classic" || type === "js_module") {
|
|
2527
2538
|
return JSON.stringify(value, null, " ");
|
|
2528
2539
|
}
|
|
2529
2540
|
if (typeof value === "string") {
|
|
@@ -4675,6 +4686,25 @@ const testAppliesDuring = (plugin, kitchen) => {
|
|
|
4675
4686
|
);
|
|
4676
4687
|
};
|
|
4677
4688
|
|
|
4689
|
+
// A bare specifier ("preact", "@jsenv/core/x.js") is resolved by node esm resolution,
|
|
4690
|
+
// everything else ("/a.js", "./a.js", "http://example.com/a.js") by url resolution
|
|
4691
|
+
const isBareSpecifier = (specifier) => {
|
|
4692
|
+
if (
|
|
4693
|
+
specifier[0] === "/" ||
|
|
4694
|
+
specifier.startsWith("./") ||
|
|
4695
|
+
specifier.startsWith("../")
|
|
4696
|
+
) {
|
|
4697
|
+
return false;
|
|
4698
|
+
}
|
|
4699
|
+
try {
|
|
4700
|
+
// eslint-disable-next-line no-new
|
|
4701
|
+
new URL(specifier);
|
|
4702
|
+
return false;
|
|
4703
|
+
} catch {
|
|
4704
|
+
return true;
|
|
4705
|
+
}
|
|
4706
|
+
};
|
|
4707
|
+
|
|
4678
4708
|
/*
|
|
4679
4709
|
* https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/css/src/CSSTransformer.js
|
|
4680
4710
|
*/
|
|
@@ -5616,7 +5646,7 @@ const parseAndTransformJsReferences = async (
|
|
|
5616
5646
|
let filenameHint;
|
|
5617
5647
|
if (
|
|
5618
5648
|
externalReferenceInfo.subtype === "import_dynamic" &&
|
|
5619
|
-
isBareSpecifier
|
|
5649
|
+
isBareSpecifier(externalReferenceInfo.specifier)
|
|
5620
5650
|
) {
|
|
5621
5651
|
filenameHint = `${externalReferenceInfo.specifier}.js`;
|
|
5622
5652
|
}
|
|
@@ -5706,23 +5736,6 @@ const parseAndTransformJsReferences = async (
|
|
|
5706
5736
|
return { content, sourcemap };
|
|
5707
5737
|
};
|
|
5708
5738
|
|
|
5709
|
-
const isBareSpecifier$2 = (specifier) => {
|
|
5710
|
-
if (
|
|
5711
|
-
specifier[0] === "/" ||
|
|
5712
|
-
specifier.startsWith("./") ||
|
|
5713
|
-
specifier.startsWith("../")
|
|
5714
|
-
) {
|
|
5715
|
-
return false;
|
|
5716
|
-
}
|
|
5717
|
-
try {
|
|
5718
|
-
// eslint-disable-next-line no-new
|
|
5719
|
-
new URL(specifier);
|
|
5720
|
-
return false;
|
|
5721
|
-
} catch {
|
|
5722
|
-
return true;
|
|
5723
|
-
}
|
|
5724
|
-
};
|
|
5725
|
-
|
|
5726
5739
|
const jsenvPluginReferenceExpectedTypes = () => {
|
|
5727
5740
|
const redirectJsReference = (reference) => {
|
|
5728
5741
|
const urlObject = new URL(reference.url);
|
|
@@ -6113,7 +6126,7 @@ const createBuildPackageConditions = (
|
|
|
6113
6126
|
for (const key of keys) {
|
|
6114
6127
|
const associatedValue = packageConditionsConfig[key];
|
|
6115
6128
|
|
|
6116
|
-
if (!isBareSpecifier
|
|
6129
|
+
if (!isBareSpecifier(key)) {
|
|
6117
6130
|
const url = new URL(key, rootDirectoryUrl);
|
|
6118
6131
|
associationsRaw[url] = associatedValue;
|
|
6119
6132
|
continue;
|
|
@@ -6148,7 +6161,7 @@ const createBuildPackageConditions = (
|
|
|
6148
6161
|
);
|
|
6149
6162
|
resolveConditionsFromSpecifier = (specifier, importer, { resolver }) => {
|
|
6150
6163
|
let associatedValue;
|
|
6151
|
-
if (isBareSpecifier
|
|
6164
|
+
if (isBareSpecifier(specifier)) {
|
|
6152
6165
|
const { url } = resolver({
|
|
6153
6166
|
specifier,
|
|
6154
6167
|
parentUrl: importer,
|
|
@@ -6173,7 +6186,7 @@ const createBuildPackageConditions = (
|
|
|
6173
6186
|
const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
|
|
6174
6187
|
// https://nodejs.org/api/esm.html#resolver-algorithm-specification
|
|
6175
6188
|
const devResolver = (specifier, importer, { resolver }) => {
|
|
6176
|
-
if (isBareSpecifier
|
|
6189
|
+
if (isBareSpecifier(specifier)) {
|
|
6177
6190
|
const { url } = resolver({
|
|
6178
6191
|
specifier,
|
|
6179
6192
|
parentUrl: importer,
|
|
@@ -6237,7 +6250,7 @@ const createBuildPackageConditions = (
|
|
|
6237
6250
|
const associations = URL_META.resolveAssociations(
|
|
6238
6251
|
{ applies: value },
|
|
6239
6252
|
(pattern) => {
|
|
6240
|
-
if (isBareSpecifier
|
|
6253
|
+
if (isBareSpecifier(pattern)) {
|
|
6241
6254
|
try {
|
|
6242
6255
|
if (pattern.endsWith("/")) {
|
|
6243
6256
|
// avoid package path not exported
|
|
@@ -6260,7 +6273,7 @@ const createBuildPackageConditions = (
|
|
|
6260
6273
|
},
|
|
6261
6274
|
);
|
|
6262
6275
|
customResolver = (specifier, importer, { resolver }) => {
|
|
6263
|
-
if (isBareSpecifier
|
|
6276
|
+
if (isBareSpecifier(specifier)) {
|
|
6264
6277
|
const { url } = resolver({
|
|
6265
6278
|
specifier,
|
|
6266
6279
|
parentUrl: importer,
|
|
@@ -6392,23 +6405,6 @@ const createResolverWithFallbackOnError = (mainResolver, fallbackResolver) => {
|
|
|
6392
6405
|
};
|
|
6393
6406
|
};
|
|
6394
6407
|
|
|
6395
|
-
const isBareSpecifier$1 = (specifier) => {
|
|
6396
|
-
if (
|
|
6397
|
-
specifier[0] === "/" ||
|
|
6398
|
-
specifier.startsWith("./") ||
|
|
6399
|
-
specifier.startsWith("../")
|
|
6400
|
-
) {
|
|
6401
|
-
return false;
|
|
6402
|
-
}
|
|
6403
|
-
try {
|
|
6404
|
-
// eslint-disable-next-line no-new
|
|
6405
|
-
new URL(specifier);
|
|
6406
|
-
return false;
|
|
6407
|
-
} catch {
|
|
6408
|
-
return true;
|
|
6409
|
-
}
|
|
6410
|
-
};
|
|
6411
|
-
|
|
6412
6408
|
const jsenvPluginNodeEsmResolution = ({
|
|
6413
6409
|
packageDirectory,
|
|
6414
6410
|
resolutionConfig = {},
|
|
@@ -6555,7 +6551,13 @@ const jsenvPluginWebResolution = () => {
|
|
|
6555
6551
|
if (ownerUrlInfo.originalUrl?.startsWith("http")) {
|
|
6556
6552
|
return new URL(resource, ownerUrlInfo.originalUrl);
|
|
6557
6553
|
}
|
|
6558
|
-
|
|
6554
|
+
// "/x" is the web meaning of a root-relative url: the root of what is
|
|
6555
|
+
// served, which is the source directory — not the directory the entry
|
|
6556
|
+
// point happens to sit in.
|
|
6557
|
+
const url = new URL(
|
|
6558
|
+
resource.slice(1),
|
|
6559
|
+
ownerUrlInfo.context.rootDirectoryUrl,
|
|
6560
|
+
);
|
|
6559
6561
|
return url;
|
|
6560
6562
|
}
|
|
6561
6563
|
// baseUrl happens second argument to new URL() is different from
|
|
@@ -7676,6 +7678,7 @@ const jsenvPluginInjections = (rawAssociations) => {
|
|
|
7676
7678
|
}
|
|
7677
7679
|
return null;
|
|
7678
7680
|
};
|
|
7681
|
+
const injectionsForUrlInfoMap = new WeakMap();
|
|
7679
7682
|
let getInjections = null;
|
|
7680
7683
|
|
|
7681
7684
|
return {
|
|
@@ -7694,8 +7697,8 @@ const jsenvPluginInjections = (rawAssociations) => {
|
|
|
7694
7697
|
});
|
|
7695
7698
|
return injectionsGetter;
|
|
7696
7699
|
};
|
|
7697
|
-
//
|
|
7698
|
-
//
|
|
7700
|
+
// errors and the build read this to know an unresolved url may come from
|
|
7701
|
+
// an injection, and word what they report accordingly
|
|
7699
7702
|
context.hasInjections = (url) => {
|
|
7700
7703
|
return Boolean(findInjectionsGetterForUrl(url));
|
|
7701
7704
|
};
|
|
@@ -7749,16 +7752,61 @@ const jsenvPluginInjections = (rawAssociations) => {
|
|
|
7749
7752
|
contentInjections: defaultInjections,
|
|
7750
7753
|
};
|
|
7751
7754
|
}
|
|
7755
|
+
injectionsForUrlInfoMap.set(urlInfo, injections);
|
|
7752
7756
|
return {
|
|
7753
|
-
contentInjections: {
|
|
7754
|
-
...defaultInjections,
|
|
7755
|
-
...injections,
|
|
7756
|
-
},
|
|
7757
|
+
contentInjections: { ...defaultInjections, ...injections },
|
|
7757
7758
|
};
|
|
7758
7759
|
},
|
|
7760
|
+
// The content still holds the placeholders when references are analyzed: they are
|
|
7761
|
+
// replaced at the very end, once the type of every inline content is known.
|
|
7762
|
+
// A specifier must not wait for that, it would resolve "__BACKEND_URL__/users/me"
|
|
7763
|
+
// as a file sitting next to the document. Only the placeholder is resolved here,
|
|
7764
|
+
// then the specifier goes to whoever resolves this kind of url (node esm, web, ...)
|
|
7765
|
+
resolveReference: (reference) => {
|
|
7766
|
+
const { ownerUrlInfo } = reference;
|
|
7767
|
+
const injections = injectionsForUrlInfoMap.get(ownerUrlInfo);
|
|
7768
|
+
if (!injections) {
|
|
7769
|
+
return null;
|
|
7770
|
+
}
|
|
7771
|
+
const { specifier, keySet } = injectIntoSpecifier(
|
|
7772
|
+
reference.specifier,
|
|
7773
|
+
injections,
|
|
7774
|
+
);
|
|
7775
|
+
if (keySet.size === 0) {
|
|
7776
|
+
return null;
|
|
7777
|
+
}
|
|
7778
|
+
reference.specifier = specifier;
|
|
7779
|
+
for (const key of keySet) {
|
|
7780
|
+
// rewriting the specifier takes the placeholder out of the content,
|
|
7781
|
+
// so the injection step must not expect to find it there
|
|
7782
|
+
ownerUrlInfo.contentInjectionUsedKeySet.add(key);
|
|
7783
|
+
}
|
|
7784
|
+
return null;
|
|
7785
|
+
},
|
|
7759
7786
|
};
|
|
7760
7787
|
};
|
|
7761
7788
|
|
|
7789
|
+
const injectIntoSpecifier = (specifier, injections) => {
|
|
7790
|
+
let specifierInjected = specifier;
|
|
7791
|
+
const keySet = new Set();
|
|
7792
|
+
for (const key of Object.keys(injections)) {
|
|
7793
|
+
if (!specifierInjected.includes(key)) {
|
|
7794
|
+
continue;
|
|
7795
|
+
}
|
|
7796
|
+
const injection = injections[key];
|
|
7797
|
+
if (!isPlaceholderInjection(injection)) {
|
|
7798
|
+
continue;
|
|
7799
|
+
}
|
|
7800
|
+
const value = readInjectionValue(injection);
|
|
7801
|
+
if (typeof value !== "string") {
|
|
7802
|
+
continue;
|
|
7803
|
+
}
|
|
7804
|
+
specifierInjected = specifierInjected.replaceAll(key, value);
|
|
7805
|
+
keySet.add(key);
|
|
7806
|
+
}
|
|
7807
|
+
return { specifier: specifierInjected, keySet };
|
|
7808
|
+
};
|
|
7809
|
+
|
|
7762
7810
|
// What a file inlines (a <script> or a <style> inside html) is authored in that file
|
|
7763
7811
|
// and inherits its injections, with two adjustments:
|
|
7764
7812
|
// - a global belongs to the file itself, injecting it into each inline content would
|
|
@@ -9833,8 +9881,10 @@ const getCorePlugins = ({
|
|
|
9833
9881
|
...(packageBundle
|
|
9834
9882
|
? [jsenvPluginWorkspaceBundle({ packageDirectory })]
|
|
9835
9883
|
: []),
|
|
9836
|
-
|
|
9884
|
+
// before reference analysis: an url written by an injection must hold its
|
|
9885
|
+
// final value when references are analyzed
|
|
9837
9886
|
jsenvPluginInjections(injections),
|
|
9887
|
+
jsenvPluginReferenceAnalysis(referenceAnalysis),
|
|
9838
9888
|
jsenvPluginTranspilation(transpilation),
|
|
9839
9889
|
// "jsenvPluginInlining" must be very soon because all other plugins will react differently once they see the file is inlined
|
|
9840
9890
|
...(inlining ? [jsenvPluginInlining()] : []),
|
|
@@ -10320,6 +10370,7 @@ const createBuildSpecifierManager = ({
|
|
|
10320
10370
|
buildDirectoryUrl,
|
|
10321
10371
|
assetsDirectory,
|
|
10322
10372
|
buildUrlsGenerator,
|
|
10373
|
+
entryKey,
|
|
10323
10374
|
base,
|
|
10324
10375
|
length = 8,
|
|
10325
10376
|
|
|
@@ -10358,6 +10409,7 @@ const createBuildSpecifierManager = ({
|
|
|
10358
10409
|
urlInfo,
|
|
10359
10410
|
ownerUrlInfo: reference.ownerUrlInfo,
|
|
10360
10411
|
assetsDirectory,
|
|
10412
|
+
entryKey,
|
|
10361
10413
|
});
|
|
10362
10414
|
}
|
|
10363
10415
|
|
|
@@ -11177,7 +11229,7 @@ const createBuildSpecifierManager = ({
|
|
|
11177
11229
|
|
|
11178
11230
|
prepareResyncResourceHints: ({ registerHtmlRefine }) => {
|
|
11179
11231
|
const hintToInjectMap = new Map();
|
|
11180
|
-
registerHtmlRefine((htmlAst, { registerHtmlMutation }) => {
|
|
11232
|
+
registerHtmlRefine((htmlAst, { registerHtmlMutation, htmlUrlInfo }) => {
|
|
11181
11233
|
visitHtmlNodes(htmlAst, {
|
|
11182
11234
|
link: (node) => {
|
|
11183
11235
|
if (getHtmlNodeAttribute(node, "jsenv-ignore") !== undefined) {
|
|
@@ -11201,12 +11253,39 @@ const createBuildSpecifierManager = ({
|
|
|
11201
11253
|
return;
|
|
11202
11254
|
}
|
|
11203
11255
|
const rawUrl = href;
|
|
11256
|
+
if (targetsAFileThatDoesNotExist(rawUrl)) {
|
|
11257
|
+
// this hint never designated anything, so nothing can explain its
|
|
11258
|
+
// removal; taking away markup written by hand on a guess is worse
|
|
11259
|
+
// than leaving it there
|
|
11260
|
+
logger.warn(
|
|
11261
|
+
createDetailedMessage(
|
|
11262
|
+
`${UNICODE.WARNING} resource hint kept as is: "${href}" cannot be resolved`,
|
|
11263
|
+
{
|
|
11264
|
+
"html file": htmlUrlInfo.url,
|
|
11265
|
+
...(rawKitchen.context.hasInjections
|
|
11266
|
+
? {
|
|
11267
|
+
suggestion: `when that url is written by an injection, jsenv resolves it in html attributes before analyzing references; check the placeholder spelling`,
|
|
11268
|
+
}
|
|
11269
|
+
: {}),
|
|
11270
|
+
},
|
|
11271
|
+
),
|
|
11272
|
+
);
|
|
11273
|
+
// the build url means nothing for something jsenv could not resolve,
|
|
11274
|
+
// and it would leak a local path into the build
|
|
11275
|
+
registerHtmlMutation(() => {
|
|
11276
|
+
setHtmlNodeAttributes(node, {
|
|
11277
|
+
href: urlToRelativeUrl(rawUrl, htmlUrlInfo.url),
|
|
11278
|
+
});
|
|
11279
|
+
});
|
|
11280
|
+
return;
|
|
11281
|
+
}
|
|
11204
11282
|
const finalUrl = internalRedirections.get(rawUrl) || rawUrl;
|
|
11205
11283
|
const urlInfo = finalKitchen.graph.getUrlInfo(finalUrl);
|
|
11206
11284
|
if (!urlInfo) {
|
|
11207
|
-
if (
|
|
11208
|
-
//
|
|
11209
|
-
//
|
|
11285
|
+
if (!href.startsWith("file:")) {
|
|
11286
|
+
// the hint designates a resource jsenv does not own: an origin for
|
|
11287
|
+
// preconnect/dns-prefetch, a remote file for the others. The author
|
|
11288
|
+
// knows what the page will request at runtime, keep it as-is.
|
|
11210
11289
|
return;
|
|
11211
11290
|
}
|
|
11212
11291
|
logger.warn(
|
|
@@ -11388,9 +11467,14 @@ const createBuildSpecifierManager = ({
|
|
|
11388
11467
|
let contentKey;
|
|
11389
11468
|
// if to guard for html where versioned build specifier is not generated
|
|
11390
11469
|
if (buildSpecifierVersioned) {
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11470
|
+
// The version goes on the build url, not on the specifier: a
|
|
11471
|
+
// specifier is written for one importer to read (base: "./" makes
|
|
11472
|
+
// it relative to that importer, base: "https://cdn…" makes it
|
|
11473
|
+
// absolute elsewhere) and says nothing about where the file lands.
|
|
11474
|
+
const buildUrlVersioned = injectVersionIntoBuildSpecifier({
|
|
11475
|
+
buildSpecifier: buildUrl,
|
|
11476
|
+
version: versionMap.get(urlInfo),
|
|
11477
|
+
versioningMethod,
|
|
11394
11478
|
});
|
|
11395
11479
|
const buildRelativeUrlVersioned = urlToRelativeUrl(
|
|
11396
11480
|
buildUrlVersioned,
|
|
@@ -11634,21 +11718,14 @@ const injectVersionIntoBuildSpecifier = ({
|
|
|
11634
11718
|
);
|
|
11635
11719
|
};
|
|
11636
11720
|
|
|
11637
|
-
const
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
}) => {
|
|
11641
|
-
if (buildSpecifierVersioned[0] === "/") {
|
|
11642
|
-
return new URL(buildSpecifierVersioned.slice(1), buildDirectoryUrl).href;
|
|
11643
|
-
}
|
|
11644
|
-
const buildUrl = new URL(buildSpecifierVersioned, buildDirectoryUrl).href;
|
|
11645
|
-
if (buildUrl.startsWith(buildDirectoryUrl)) {
|
|
11646
|
-
return buildUrl;
|
|
11721
|
+
const targetsAFileThatDoesNotExist = (url) => {
|
|
11722
|
+
if (!url.startsWith("file:")) {
|
|
11723
|
+
return false;
|
|
11647
11724
|
}
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
return
|
|
11725
|
+
const urlObject = new URL(url);
|
|
11726
|
+
urlObject.search = "";
|
|
11727
|
+
urlObject.hash = "";
|
|
11728
|
+
return !existsSync(urlObject);
|
|
11652
11729
|
};
|
|
11653
11730
|
|
|
11654
11731
|
// import { ANSI } from "@jsenv/humanize";
|
|
@@ -11678,12 +11755,41 @@ const createBuildUrlsGenerator = ({
|
|
|
11678
11755
|
};
|
|
11679
11756
|
|
|
11680
11757
|
const nameSetPerDirectoryMap = new Map();
|
|
11681
|
-
const
|
|
11682
|
-
|
|
11758
|
+
const reserveName = (directoryPath, urlName) => {
|
|
11759
|
+
let nameSet = nameSetPerDirectoryMap.get(directoryPath);
|
|
11760
|
+
if (!nameSet) {
|
|
11761
|
+
nameSet = new Set();
|
|
11762
|
+
nameSetPerDirectoryMap.set(directoryPath, nameSet);
|
|
11763
|
+
}
|
|
11764
|
+
let [basename, extension] = splitFileExtension(urlName);
|
|
11765
|
+
extension = extensionMappings[extension] || extension;
|
|
11766
|
+
let nameCandidate = `${basename}${extension}`; // reconstruct name in case extension was normalized
|
|
11767
|
+
let integer = 1;
|
|
11768
|
+
while (nameSet.has(nameCandidate)) {
|
|
11769
|
+
integer++;
|
|
11770
|
+
nameCandidate = `${basename}${integer}${extension}`;
|
|
11771
|
+
}
|
|
11772
|
+
nameSet.add(nameCandidate);
|
|
11773
|
+
return nameCandidate;
|
|
11774
|
+
};
|
|
11775
|
+
const generate = (
|
|
11776
|
+
url,
|
|
11777
|
+
{ urlInfo, ownerUrlInfo, assetsDirectory, entryKey },
|
|
11778
|
+
) => {
|
|
11779
|
+
// A url already inside the build directory names a chunk a bundler just
|
|
11780
|
+
// produced, and each entry point is bundled on its own: two of them
|
|
11781
|
+
// routinely produce a chunk of the same name holding different code (the
|
|
11782
|
+
// shared dependencies of THAT entry point, exported under names decided by
|
|
11783
|
+
// THAT bundle). They are told apart by the entry point they come from —
|
|
11784
|
+
// sharing the file would leave one entry importing exports the file on disk
|
|
11785
|
+
// does not have.
|
|
11786
|
+
const insideBuildDirectory = urlIsOrIsInsideOf(url, buildDirectoryUrl);
|
|
11787
|
+
const key = insideBuildDirectory ? `${entryKey} ${url}` : url;
|
|
11788
|
+
const buildUrlFromMap = buildUrlMap.get(key);
|
|
11683
11789
|
if (buildUrlFromMap) {
|
|
11684
11790
|
return buildUrlFromMap;
|
|
11685
11791
|
}
|
|
11686
|
-
if (
|
|
11792
|
+
if (insideBuildDirectory) {
|
|
11687
11793
|
if (ownerUrlInfo.searchParams.has("dynamic_import_id")) {
|
|
11688
11794
|
const ownerDirectoryPath = determineDirectoryPath({
|
|
11689
11795
|
sourceDirectoryUrl,
|
|
@@ -11695,11 +11801,18 @@ const createBuildUrlsGenerator = ({
|
|
|
11695
11801
|
buildUrl = injectQueryParams(buildUrl, {
|
|
11696
11802
|
dynamic_import_id: undefined,
|
|
11697
11803
|
});
|
|
11698
|
-
associateBuildUrl(
|
|
11804
|
+
associateBuildUrl(key, buildUrl);
|
|
11699
11805
|
return buildUrl;
|
|
11700
11806
|
}
|
|
11701
|
-
|
|
11702
|
-
|
|
11807
|
+
const urlObject = new URL(url);
|
|
11808
|
+
const chunkDirectoryPath = urlToRelativeUrl(
|
|
11809
|
+
new URL("./", urlObject),
|
|
11810
|
+
buildDirectoryUrl,
|
|
11811
|
+
);
|
|
11812
|
+
const chunkName = reserveName(chunkDirectoryPath, urlToFilename(url));
|
|
11813
|
+
const buildUrl = `${buildDirectoryUrl}${chunkDirectoryPath}${chunkName}${urlObject.search}${urlObject.hash}`;
|
|
11814
|
+
associateBuildUrl(key, buildUrl);
|
|
11815
|
+
return buildUrl;
|
|
11703
11816
|
}
|
|
11704
11817
|
if (urlInfo.type === "entry_build") {
|
|
11705
11818
|
const buildUrl = new URL(urlInfo.filenameHint, buildDirectoryUrl).href;
|
|
@@ -11731,25 +11844,10 @@ const createBuildUrlsGenerator = ({
|
|
|
11731
11844
|
urlInfo,
|
|
11732
11845
|
ownerUrlInfo,
|
|
11733
11846
|
});
|
|
11734
|
-
let nameSet = nameSetPerDirectoryMap.get(directoryPath);
|
|
11735
|
-
if (!nameSet) {
|
|
11736
|
-
nameSet = new Set();
|
|
11737
|
-
nameSetPerDirectoryMap.set(directoryPath, nameSet);
|
|
11738
|
-
}
|
|
11739
11847
|
const urlObject = new URL(url);
|
|
11740
11848
|
injectQueryParams(urlObject, { dynamic_import_id: undefined });
|
|
11741
11849
|
let { search, hash } = urlObject;
|
|
11742
|
-
|
|
11743
|
-
let [basename, extension] = splitFileExtension(urlName);
|
|
11744
|
-
extension = extensionMappings[extension] || extension;
|
|
11745
|
-
let nameCandidate = `${basename}${extension}`; // reconstruct name in case extension was normalized
|
|
11746
|
-
let integer = 1;
|
|
11747
|
-
while (nameSet.has(nameCandidate)) {
|
|
11748
|
-
integer++;
|
|
11749
|
-
nameCandidate = `${basename}${integer}${extension}`;
|
|
11750
|
-
}
|
|
11751
|
-
const name = nameCandidate;
|
|
11752
|
-
nameSet.add(name);
|
|
11850
|
+
const name = reserveName(directoryPath, getUrlName(url, urlInfo));
|
|
11753
11851
|
const buildUrl = `${buildDirectoryUrl}${directoryPath}${name}${search}${hash}`;
|
|
11754
11852
|
associateBuildUrl(url, buildUrl);
|
|
11755
11853
|
return buildUrl;
|
|
@@ -13136,6 +13234,7 @@ const prepareEntryPointBuild = async (
|
|
|
13136
13234
|
base,
|
|
13137
13235
|
assetsDirectory,
|
|
13138
13236
|
buildUrlsGenerator,
|
|
13237
|
+
entryKey: sourceRelativeUrl,
|
|
13139
13238
|
|
|
13140
13239
|
versioning,
|
|
13141
13240
|
versioningMethod,
|
|
@@ -13374,7 +13473,10 @@ const prepareEntryPointBuild = async (
|
|
|
13374
13473
|
const registerHtmlMutation = (callback) => {
|
|
13375
13474
|
htmlMutationCallbackSet.add(callback);
|
|
13376
13475
|
};
|
|
13377
|
-
htmlRefine(htmlAst, {
|
|
13476
|
+
htmlRefine(htmlAst, {
|
|
13477
|
+
registerHtmlMutation,
|
|
13478
|
+
htmlUrlInfo: urlInfo,
|
|
13479
|
+
});
|
|
13378
13480
|
for (const htmlMutationCallback of htmlMutationCallbackSet) {
|
|
13379
13481
|
htmlMutationCallback();
|
|
13380
13482
|
}
|
|
@@ -13459,21 +13561,4 @@ const prepareEntryPointBuild = async (
|
|
|
13459
13561
|
};
|
|
13460
13562
|
};
|
|
13461
13563
|
|
|
13462
|
-
const isBareSpecifier = (specifier) => {
|
|
13463
|
-
if (
|
|
13464
|
-
specifier[0] === "/" ||
|
|
13465
|
-
specifier.startsWith("./") ||
|
|
13466
|
-
specifier.startsWith("../")
|
|
13467
|
-
) {
|
|
13468
|
-
return false;
|
|
13469
|
-
}
|
|
13470
|
-
try {
|
|
13471
|
-
// eslint-disable-next-line no-new
|
|
13472
|
-
new URL(specifier);
|
|
13473
|
-
return false;
|
|
13474
|
-
} catch {
|
|
13475
|
-
return true;
|
|
13476
|
-
}
|
|
13477
|
-
};
|
|
13478
|
-
|
|
13479
13564
|
export { build };
|