@jsenv/core 39.3.5 → 39.3.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/README.md +1 -1
- package/dist/jsenv_core.js +120 -103
- package/package.json +1 -1
- package/src/dev/start_dev_server.js +10 -9
- package/src/kitchen/errors.js +13 -3
- package/src/kitchen/kitchen.js +36 -40
- package/src/plugins/directory_reference_effect/jsenv_plugin_directory_reference_effect.js +5 -1
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +5 -9
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +15 -2
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +38 -39
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Jsenv is a suite of tools that can be used in projects involving JavaScript.
|
|
|
14
14
|
It favors standards and simplicity.
|
|
15
15
|
As a result it can be enjoyed by people without much experience in tooling or seeking for simple tools without hidden complexities.
|
|
16
16
|
|
|
17
|
-
If you want to try jsenv on your machine, use [@jsenv/cli](./packages/related/cli
|
|
17
|
+
If you want to try jsenv on your machine, use [@jsenv/cli](./packages/related/cli/#jsenvcli).
|
|
18
18
|
|
|
19
19
|
Link to [documentation](./md/users/users.md)
|
|
20
20
|
|
package/dist/jsenv_core.js
CHANGED
|
@@ -11562,6 +11562,7 @@ ${reason}`,
|
|
|
11562
11562
|
),
|
|
11563
11563
|
);
|
|
11564
11564
|
defineNonEnumerableProperties(resolveError, {
|
|
11565
|
+
isJsenvCookingError: true,
|
|
11565
11566
|
name: "RESOLVE_URL_ERROR",
|
|
11566
11567
|
code,
|
|
11567
11568
|
reason,
|
|
@@ -11610,6 +11611,7 @@ ${reason}`,
|
|
|
11610
11611
|
),
|
|
11611
11612
|
);
|
|
11612
11613
|
defineNonEnumerableProperties(fetchError, {
|
|
11614
|
+
isJsenvCookingError: true,
|
|
11613
11615
|
name: "FETCH_URL_CONTENT_ERROR",
|
|
11614
11616
|
code,
|
|
11615
11617
|
reason,
|
|
@@ -11670,6 +11672,9 @@ const createTransformUrlContentError = ({
|
|
|
11670
11672
|
return error;
|
|
11671
11673
|
}
|
|
11672
11674
|
if (error.code === "PARSE_ERROR") {
|
|
11675
|
+
if (error.isJsenvCookingError) {
|
|
11676
|
+
return error;
|
|
11677
|
+
}
|
|
11673
11678
|
const reference = urlInfo.firstReference;
|
|
11674
11679
|
let trace = reference.trace;
|
|
11675
11680
|
let line = error.line;
|
|
@@ -11717,13 +11722,16 @@ const createTransformUrlContentError = ({
|
|
|
11717
11722
|
${trace.message}
|
|
11718
11723
|
${error.message}`,
|
|
11719
11724
|
{
|
|
11720
|
-
"first reference":
|
|
11725
|
+
"first reference": reference.trace.url
|
|
11726
|
+
? `${reference.trace.url}:${reference.trace.line}:${reference.trace.column}`
|
|
11727
|
+
: reference.trace.message,
|
|
11721
11728
|
...detailsFromFirstReference(reference),
|
|
11722
11729
|
...detailsFromPluginController(pluginController),
|
|
11723
11730
|
},
|
|
11724
11731
|
),
|
|
11725
11732
|
);
|
|
11726
11733
|
defineNonEnumerableProperties(transformError, {
|
|
11734
|
+
isJsenvCookingError: true,
|
|
11727
11735
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
11728
11736
|
code: "PARSE_ERROR",
|
|
11729
11737
|
reason: error.message,
|
|
@@ -11753,6 +11761,7 @@ ${reason}`,
|
|
|
11753
11761
|
),
|
|
11754
11762
|
);
|
|
11755
11763
|
defineNonEnumerableProperties(transformError, {
|
|
11764
|
+
isJsenvCookingError: true,
|
|
11756
11765
|
cause: error,
|
|
11757
11766
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
11758
11767
|
code,
|
|
@@ -11788,6 +11797,7 @@ ${reference.trace.message}`,
|
|
|
11788
11797
|
),
|
|
11789
11798
|
);
|
|
11790
11799
|
defineNonEnumerableProperties(finalizeError, {
|
|
11800
|
+
isJsenvCookingError: true,
|
|
11791
11801
|
...(error && error instanceof Error ? { cause: error } : {}),
|
|
11792
11802
|
name: "FINALIZE_URL_CONTENT_ERROR",
|
|
11793
11803
|
reason: `"finalizeUrlContent" error on "${urlInfo.type}"`,
|
|
@@ -11849,9 +11859,9 @@ const detailsFromValueThrown = (valueThrownByPlugin) => {
|
|
|
11849
11859
|
};
|
|
11850
11860
|
};
|
|
11851
11861
|
|
|
11852
|
-
const defineNonEnumerableProperties = (
|
|
11862
|
+
const defineNonEnumerableProperties = (object, properties) => {
|
|
11853
11863
|
for (const key of Object.keys(properties)) {
|
|
11854
|
-
Object.defineProperty(
|
|
11864
|
+
Object.defineProperty(object, key, {
|
|
11855
11865
|
configurable: true,
|
|
11856
11866
|
writable: true,
|
|
11857
11867
|
value: properties[key],
|
|
@@ -14486,7 +14496,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
14486
14496
|
urlInfo,
|
|
14487
14497
|
error,
|
|
14488
14498
|
});
|
|
14489
|
-
urlInfo.error = transformError;
|
|
14490
14499
|
throw transformError;
|
|
14491
14500
|
}
|
|
14492
14501
|
};
|
|
@@ -14518,9 +14527,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
14518
14527
|
|
|
14519
14528
|
// urlInfo objects are reused, they must be "reset" before cooking them again
|
|
14520
14529
|
if (urlInfo.error || urlInfo.content !== undefined) {
|
|
14521
|
-
if (urlInfo.isInline) {
|
|
14522
|
-
return;
|
|
14523
|
-
}
|
|
14524
14530
|
urlInfo.error = null;
|
|
14525
14531
|
urlInfo.type = null;
|
|
14526
14532
|
urlInfo.subtype = null;
|
|
@@ -14542,30 +14548,46 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
14542
14548
|
});
|
|
14543
14549
|
} catch (e) {
|
|
14544
14550
|
urlInfo.error = e;
|
|
14545
|
-
if (
|
|
14546
|
-
urlInfo.
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
14550
|
-
|
|
14551
|
-
|
|
14552
|
-
|
|
14553
|
-
|
|
14554
|
-
|
|
14551
|
+
if (urlInfo.isInline) {
|
|
14552
|
+
const parentUrlInfo = urlInfo.findParentIfInline();
|
|
14553
|
+
parentUrlInfo.error = e;
|
|
14554
|
+
}
|
|
14555
|
+
let errorWrapperMessage;
|
|
14556
|
+
if (e.code === "PARSE_ERROR") {
|
|
14557
|
+
errorWrapperMessage =
|
|
14558
|
+
e.name === "TRANSFORM_URL_CONTENT_ERROR"
|
|
14559
|
+
? e.message
|
|
14560
|
+
: `parse error on "${urlInfo.type}"
|
|
14555
14561
|
${e.trace?.message}
|
|
14556
14562
|
${e.reason}
|
|
14557
14563
|
--- declared in ---
|
|
14558
|
-
${urlInfo.firstReference.trace.message}
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14562
|
-
|
|
14563
|
-
${urlInfo.firstReference.trace.message}
|
|
14564
|
-
|
|
14565
|
-
|
|
14564
|
+
${urlInfo.firstReference.trace.message}`;
|
|
14565
|
+
} else if (e.isJsenvCookingError) {
|
|
14566
|
+
errorWrapperMessage = e.message;
|
|
14567
|
+
} else {
|
|
14568
|
+
errorWrapperMessage = `Error while cooking ${urlInfo.type}
|
|
14569
|
+
${urlInfo.firstReference.trace.message}`;
|
|
14570
|
+
}
|
|
14571
|
+
// if we are cooking inline content during dev it's better not to throw
|
|
14572
|
+
// because the main url info (html) is still valid and can be returned to the browser
|
|
14573
|
+
if (
|
|
14574
|
+
urlInfo.isInline &&
|
|
14575
|
+
urlInfo.context.dev &&
|
|
14576
|
+
// but if we are explicitely requesting inline content file then we throw
|
|
14577
|
+
// to properly send 500 to the browser
|
|
14578
|
+
urlInfo.context.reference !== urlInfo.url
|
|
14579
|
+
) {
|
|
14580
|
+
logger.error(errorWrapperMessage);
|
|
14566
14581
|
return;
|
|
14567
14582
|
}
|
|
14568
|
-
|
|
14583
|
+
if (e.isJsenvCookingError) {
|
|
14584
|
+
throw e;
|
|
14585
|
+
}
|
|
14586
|
+
const error = new Error(errorWrapperMessage, { cause: e });
|
|
14587
|
+
defineNonEnumerableProperties(error, {
|
|
14588
|
+
__INTERNAL_ERROR__: true,
|
|
14589
|
+
});
|
|
14590
|
+
throw error;
|
|
14569
14591
|
}
|
|
14570
14592
|
}
|
|
14571
14593
|
|
|
@@ -14655,23 +14677,6 @@ ${e.stack}`,
|
|
|
14655
14677
|
return kitchen;
|
|
14656
14678
|
};
|
|
14657
14679
|
|
|
14658
|
-
// if we are cooking the inline content internally it's better not to throw
|
|
14659
|
-
// because the main url info (html) is still valid
|
|
14660
|
-
// but if we are explicitely requesting inline content during dev
|
|
14661
|
-
// then we should throw
|
|
14662
|
-
const errorOnInlineContentCanSkipThrow = (urlInfo) => {
|
|
14663
|
-
if (urlInfo.context.build) {
|
|
14664
|
-
return true;
|
|
14665
|
-
}
|
|
14666
|
-
if (
|
|
14667
|
-
urlInfo.context.reference &&
|
|
14668
|
-
urlInfo.context.reference.url === urlInfo.url
|
|
14669
|
-
) {
|
|
14670
|
-
return false;
|
|
14671
|
-
}
|
|
14672
|
-
return true;
|
|
14673
|
-
};
|
|
14674
|
-
|
|
14675
14680
|
const debounceCook = (cook) => {
|
|
14676
14681
|
const pendingDishes = new Map();
|
|
14677
14682
|
return async (urlInfo, context) => {
|
|
@@ -15047,7 +15052,10 @@ const jsenvPluginDirectoryReferenceEffect = (
|
|
|
15047
15052
|
}
|
|
15048
15053
|
if (actionForDirectory === "error") {
|
|
15049
15054
|
const error = new Error("Reference leads to a directory");
|
|
15050
|
-
error
|
|
15055
|
+
defineNonEnumerableProperties(error, {
|
|
15056
|
+
isJsenvCookingError: true,
|
|
15057
|
+
code: "DIRECTORY_REFERENCE_NOT_ALLOWED",
|
|
15058
|
+
});
|
|
15051
15059
|
throw error;
|
|
15052
15060
|
}
|
|
15053
15061
|
if (actionForDirectory === "preserve") {
|
|
@@ -16450,13 +16458,8 @@ const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
16450
16458
|
});
|
|
16451
16459
|
|
|
16452
16460
|
actions.push(async () => {
|
|
16453
|
-
|
|
16454
|
-
|
|
16455
|
-
} catch (e) {
|
|
16456
|
-
if (!e || e.code !== "PARSE_ERROR") {
|
|
16457
|
-
throw e;
|
|
16458
|
-
}
|
|
16459
|
-
}
|
|
16461
|
+
const inlineUrlInfo = inlineReference.urlInfo;
|
|
16462
|
+
await inlineUrlInfo.cook();
|
|
16460
16463
|
mutations.push(() => {
|
|
16461
16464
|
if (hotAccept) {
|
|
16462
16465
|
removeHtmlNodeText(node);
|
|
@@ -16464,7 +16467,7 @@ const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
16464
16467
|
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
16465
16468
|
});
|
|
16466
16469
|
} else {
|
|
16467
|
-
setHtmlNodeText(node,
|
|
16470
|
+
setHtmlNodeText(node, inlineUrlInfo.content, {
|
|
16468
16471
|
indentation: false, // indentation would decrease stack trace precision
|
|
16469
16472
|
});
|
|
16470
16473
|
setHtmlNodeAttributes(node, {
|
|
@@ -16737,7 +16740,8 @@ const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
16737
16740
|
}
|
|
16738
16741
|
mutations.forEach((mutation) => mutation());
|
|
16739
16742
|
mutations.length = 0;
|
|
16740
|
-
|
|
16743
|
+
const html = stringifyHtmlAst(htmlAst);
|
|
16744
|
+
return html;
|
|
16741
16745
|
} catch (e) {
|
|
16742
16746
|
importmapLoaded();
|
|
16743
16747
|
throw e;
|
|
@@ -17104,8 +17108,12 @@ const jsenvPluginInlineContentFetcher = () => {
|
|
|
17104
17108
|
// when updating the file, first reference is the previous version
|
|
17105
17109
|
// - we cannot use urlInfo.lastReference because it can be the reference created by "http_request"
|
|
17106
17110
|
let lastInlineReference;
|
|
17111
|
+
let originalContent = urlInfo.originalContent;
|
|
17107
17112
|
for (const reference of urlInfo.referenceFromOthersSet) {
|
|
17108
17113
|
if (reference.isInline) {
|
|
17114
|
+
if (originalContent === undefined) {
|
|
17115
|
+
originalContent = reference.content;
|
|
17116
|
+
}
|
|
17109
17117
|
lastInlineReference = reference;
|
|
17110
17118
|
}
|
|
17111
17119
|
}
|
|
@@ -17120,8 +17128,17 @@ const jsenvPluginInlineContentFetcher = () => {
|
|
|
17120
17128
|
}
|
|
17121
17129
|
}
|
|
17122
17130
|
return {
|
|
17123
|
-
originalContent
|
|
17124
|
-
content:
|
|
17131
|
+
originalContent,
|
|
17132
|
+
content:
|
|
17133
|
+
// we must favor original content to re-apply the same plugin logic
|
|
17134
|
+
// so that the same references are generated
|
|
17135
|
+
// without this we would try to resolve references like
|
|
17136
|
+
// "/node_modules/package/file.js" instead of "package/file.js"
|
|
17137
|
+
// meaning we would not create the implicit dependency to package.json
|
|
17138
|
+
// resulting in a reload of the browser (as implicit reference to package.json is gone)
|
|
17139
|
+
originalContent === undefined
|
|
17140
|
+
? lastInlineReference.content
|
|
17141
|
+
: originalContent,
|
|
17125
17142
|
contentType: lastInlineReference.contentType,
|
|
17126
17143
|
};
|
|
17127
17144
|
},
|
|
@@ -18274,47 +18291,46 @@ const createNodeEsmResolver = ({
|
|
|
18274
18291
|
specifier: reference.specifier,
|
|
18275
18292
|
preservesSymlink,
|
|
18276
18293
|
});
|
|
18277
|
-
if (ownerUrlInfo.context.
|
|
18278
|
-
|
|
18279
|
-
type !== "relative_specifier" &&
|
|
18280
|
-
type !== "absolute_specifier" &&
|
|
18281
|
-
type !== "node_builtin_specifier";
|
|
18282
|
-
if (dependsOnPackageJson) {
|
|
18283
|
-
// this reference depends on package.json and node_modules
|
|
18284
|
-
// to be resolved. Each file using this specifier
|
|
18285
|
-
// must be invalidated when corresponding package.json changes
|
|
18286
|
-
addRelationshipWithPackageJson({
|
|
18287
|
-
reference,
|
|
18288
|
-
packageJsonUrl: `${packageDirectoryUrl}package.json`,
|
|
18289
|
-
field: type.startsWith("field:")
|
|
18290
|
-
? `#${type.slice("field:".length)}`
|
|
18291
|
-
: "",
|
|
18292
|
-
});
|
|
18293
|
-
}
|
|
18294
|
+
if (ownerUrlInfo.context.build) {
|
|
18295
|
+
return url;
|
|
18294
18296
|
}
|
|
18295
|
-
|
|
18296
|
-
|
|
18297
|
-
|
|
18298
|
-
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
|
|
18311
|
-
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
18297
|
+
const dependsOnPackageJson =
|
|
18298
|
+
type !== "relative_specifier" &&
|
|
18299
|
+
type !== "absolute_specifier" &&
|
|
18300
|
+
type !== "node_builtin_specifier";
|
|
18301
|
+
if (dependsOnPackageJson) {
|
|
18302
|
+
// this reference depends on package.json and node_modules
|
|
18303
|
+
// to be resolved. Each file using this specifier
|
|
18304
|
+
// must be invalidated when corresponding package.json changes
|
|
18305
|
+
addRelationshipWithPackageJson({
|
|
18306
|
+
reference,
|
|
18307
|
+
packageJsonUrl: `${packageDirectoryUrl}package.json`,
|
|
18308
|
+
field: type.startsWith("field:")
|
|
18309
|
+
? `#${type.slice("field:".length)}`
|
|
18310
|
+
: "",
|
|
18311
|
+
});
|
|
18312
|
+
}
|
|
18313
|
+
// without this check a file inside a project without package.json
|
|
18314
|
+
// could be considered as a node module if there is a ancestor package.json
|
|
18315
|
+
// but we want to version only node modules
|
|
18316
|
+
if (url.includes("/node_modules/")) {
|
|
18317
|
+
const packageDirectoryUrl = defaultLookupPackageScope(url);
|
|
18318
|
+
if (
|
|
18319
|
+
packageDirectoryUrl &&
|
|
18320
|
+
packageDirectoryUrl !== ownerUrlInfo.context.rootDirectoryUrl
|
|
18321
|
+
) {
|
|
18322
|
+
const packageVersion =
|
|
18323
|
+
defaultReadPackageJson(packageDirectoryUrl).version;
|
|
18324
|
+
// package version can be null, see https://github.com/babel/babel/blob/2ce56e832c2dd7a7ed92c89028ba929f874c2f5c/packages/babel-runtime/helpers/esm/package.json#L2
|
|
18325
|
+
if (packageVersion) {
|
|
18326
|
+
addRelationshipWithPackageJson({
|
|
18327
|
+
reference,
|
|
18328
|
+
packageJsonUrl: `${packageDirectoryUrl}package.json`,
|
|
18329
|
+
field: "version",
|
|
18330
|
+
hasVersioningEffect: true,
|
|
18331
|
+
});
|
|
18317
18332
|
}
|
|
18333
|
+
reference.version = packageVersion;
|
|
18318
18334
|
}
|
|
18319
18335
|
}
|
|
18320
18336
|
return url;
|
|
@@ -23241,7 +23257,6 @@ const startDevServer = async ({
|
|
|
23241
23257
|
};
|
|
23242
23258
|
}
|
|
23243
23259
|
}
|
|
23244
|
-
|
|
23245
23260
|
await urlInfo.cook({ request, reference });
|
|
23246
23261
|
let { response } = urlInfo;
|
|
23247
23262
|
if (response) {
|
|
@@ -23284,9 +23299,8 @@ const startDevServer = async ({
|
|
|
23284
23299
|
},
|
|
23285
23300
|
);
|
|
23286
23301
|
return response;
|
|
23287
|
-
} catch (
|
|
23288
|
-
|
|
23289
|
-
const originalError = e ? e.cause || e : e;
|
|
23302
|
+
} catch (error) {
|
|
23303
|
+
const originalError = error ? error.cause || error : error;
|
|
23290
23304
|
if (originalError.asResponse) {
|
|
23291
23305
|
return originalError.asResponse();
|
|
23292
23306
|
}
|
|
@@ -23298,13 +23312,13 @@ const startDevServer = async ({
|
|
|
23298
23312
|
if (urlInfo.content !== undefined) {
|
|
23299
23313
|
kitchen.context.logger.error(`Error while handling ${request.url}:
|
|
23300
23314
|
${originalError.reasonCode || originalError.code}
|
|
23301
|
-
${
|
|
23315
|
+
${error.trace?.message}`);
|
|
23302
23316
|
return {
|
|
23303
23317
|
url: reference.url,
|
|
23304
23318
|
status: 200,
|
|
23305
23319
|
// reason becomes the http response statusText, it must not contain invalid chars
|
|
23306
23320
|
// https://github.com/nodejs/node/blob/0c27ca4bc9782d658afeaebcec85ec7b28f1cc35/lib/_http_common.js#L221
|
|
23307
|
-
statusText:
|
|
23321
|
+
statusText: error.reason,
|
|
23308
23322
|
statusMessage: originalError.message,
|
|
23309
23323
|
headers: {
|
|
23310
23324
|
"content-type": urlInfo.contentType,
|
|
@@ -23317,7 +23331,7 @@ ${e.trace?.message}`);
|
|
|
23317
23331
|
return {
|
|
23318
23332
|
url: reference.url,
|
|
23319
23333
|
status: 500,
|
|
23320
|
-
statusText:
|
|
23334
|
+
statusText: error.reason,
|
|
23321
23335
|
statusMessage: originalError.message,
|
|
23322
23336
|
headers: {
|
|
23323
23337
|
"cache-control": "no-store",
|
|
@@ -23352,8 +23366,11 @@ ${e.trace?.message}`);
|
|
|
23352
23366
|
return {
|
|
23353
23367
|
url: reference.url,
|
|
23354
23368
|
status: 500,
|
|
23355
|
-
statusText:
|
|
23356
|
-
statusMessage:
|
|
23369
|
+
statusText: error.reason,
|
|
23370
|
+
statusMessage: error.stack,
|
|
23371
|
+
headers: {
|
|
23372
|
+
"cache-control": "no-store",
|
|
23373
|
+
},
|
|
23357
23374
|
};
|
|
23358
23375
|
}
|
|
23359
23376
|
},
|
package/package.json
CHANGED
|
@@ -448,7 +448,6 @@ export const startDevServer = async ({
|
|
|
448
448
|
};
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
-
|
|
452
451
|
await urlInfo.cook({ request, reference });
|
|
453
452
|
let { response } = urlInfo;
|
|
454
453
|
if (response) {
|
|
@@ -491,9 +490,8 @@ export const startDevServer = async ({
|
|
|
491
490
|
},
|
|
492
491
|
);
|
|
493
492
|
return response;
|
|
494
|
-
} catch (
|
|
495
|
-
|
|
496
|
-
const originalError = e ? e.cause || e : e;
|
|
493
|
+
} catch (error) {
|
|
494
|
+
const originalError = error ? error.cause || error : error;
|
|
497
495
|
if (originalError.asResponse) {
|
|
498
496
|
return originalError.asResponse();
|
|
499
497
|
}
|
|
@@ -505,13 +503,13 @@ export const startDevServer = async ({
|
|
|
505
503
|
if (urlInfo.content !== undefined) {
|
|
506
504
|
kitchen.context.logger.error(`Error while handling ${request.url}:
|
|
507
505
|
${originalError.reasonCode || originalError.code}
|
|
508
|
-
${
|
|
506
|
+
${error.trace?.message}`);
|
|
509
507
|
return {
|
|
510
508
|
url: reference.url,
|
|
511
509
|
status: 200,
|
|
512
510
|
// reason becomes the http response statusText, it must not contain invalid chars
|
|
513
511
|
// https://github.com/nodejs/node/blob/0c27ca4bc9782d658afeaebcec85ec7b28f1cc35/lib/_http_common.js#L221
|
|
514
|
-
statusText:
|
|
512
|
+
statusText: error.reason,
|
|
515
513
|
statusMessage: originalError.message,
|
|
516
514
|
headers: {
|
|
517
515
|
"content-type": urlInfo.contentType,
|
|
@@ -524,7 +522,7 @@ ${e.trace?.message}`);
|
|
|
524
522
|
return {
|
|
525
523
|
url: reference.url,
|
|
526
524
|
status: 500,
|
|
527
|
-
statusText:
|
|
525
|
+
statusText: error.reason,
|
|
528
526
|
statusMessage: originalError.message,
|
|
529
527
|
headers: {
|
|
530
528
|
"cache-control": "no-store",
|
|
@@ -559,8 +557,11 @@ ${e.trace?.message}`);
|
|
|
559
557
|
return {
|
|
560
558
|
url: reference.url,
|
|
561
559
|
status: 500,
|
|
562
|
-
statusText:
|
|
563
|
-
statusMessage:
|
|
560
|
+
statusText: error.reason,
|
|
561
|
+
statusMessage: error.stack,
|
|
562
|
+
headers: {
|
|
563
|
+
"cache-control": "no-store",
|
|
564
|
+
},
|
|
564
565
|
};
|
|
565
566
|
}
|
|
566
567
|
},
|
package/src/kitchen/errors.js
CHANGED
|
@@ -25,6 +25,7 @@ ${reason}`,
|
|
|
25
25
|
),
|
|
26
26
|
);
|
|
27
27
|
defineNonEnumerableProperties(resolveError, {
|
|
28
|
+
isJsenvCookingError: true,
|
|
28
29
|
name: "RESOLVE_URL_ERROR",
|
|
29
30
|
code,
|
|
30
31
|
reason,
|
|
@@ -73,6 +74,7 @@ ${reason}`,
|
|
|
73
74
|
),
|
|
74
75
|
);
|
|
75
76
|
defineNonEnumerableProperties(fetchError, {
|
|
77
|
+
isJsenvCookingError: true,
|
|
76
78
|
name: "FETCH_URL_CONTENT_ERROR",
|
|
77
79
|
code,
|
|
78
80
|
reason,
|
|
@@ -133,6 +135,9 @@ export const createTransformUrlContentError = ({
|
|
|
133
135
|
return error;
|
|
134
136
|
}
|
|
135
137
|
if (error.code === "PARSE_ERROR") {
|
|
138
|
+
if (error.isJsenvCookingError) {
|
|
139
|
+
return error;
|
|
140
|
+
}
|
|
136
141
|
const reference = urlInfo.firstReference;
|
|
137
142
|
let trace = reference.trace;
|
|
138
143
|
let line = error.line;
|
|
@@ -180,13 +185,16 @@ export const createTransformUrlContentError = ({
|
|
|
180
185
|
${trace.message}
|
|
181
186
|
${error.message}`,
|
|
182
187
|
{
|
|
183
|
-
"first reference":
|
|
188
|
+
"first reference": reference.trace.url
|
|
189
|
+
? `${reference.trace.url}:${reference.trace.line}:${reference.trace.column}`
|
|
190
|
+
: reference.trace.message,
|
|
184
191
|
...detailsFromFirstReference(reference),
|
|
185
192
|
...detailsFromPluginController(pluginController),
|
|
186
193
|
},
|
|
187
194
|
),
|
|
188
195
|
);
|
|
189
196
|
defineNonEnumerableProperties(transformError, {
|
|
197
|
+
isJsenvCookingError: true,
|
|
190
198
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
191
199
|
code: "PARSE_ERROR",
|
|
192
200
|
reason: error.message,
|
|
@@ -216,6 +224,7 @@ ${reason}`,
|
|
|
216
224
|
),
|
|
217
225
|
);
|
|
218
226
|
defineNonEnumerableProperties(transformError, {
|
|
227
|
+
isJsenvCookingError: true,
|
|
219
228
|
cause: error,
|
|
220
229
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
221
230
|
code,
|
|
@@ -251,6 +260,7 @@ ${reference.trace.message}`,
|
|
|
251
260
|
),
|
|
252
261
|
);
|
|
253
262
|
defineNonEnumerableProperties(finalizeError, {
|
|
263
|
+
isJsenvCookingError: true,
|
|
254
264
|
...(error && error instanceof Error ? { cause: error } : {}),
|
|
255
265
|
name: "FINALIZE_URL_CONTENT_ERROR",
|
|
256
266
|
reason: `"finalizeUrlContent" error on "${urlInfo.type}"`,
|
|
@@ -312,9 +322,9 @@ const detailsFromValueThrown = (valueThrownByPlugin) => {
|
|
|
312
322
|
};
|
|
313
323
|
};
|
|
314
324
|
|
|
315
|
-
const defineNonEnumerableProperties = (
|
|
325
|
+
export const defineNonEnumerableProperties = (object, properties) => {
|
|
316
326
|
for (const key of Object.keys(properties)) {
|
|
317
|
-
Object.defineProperty(
|
|
327
|
+
Object.defineProperty(object, key, {
|
|
318
328
|
configurable: true,
|
|
319
329
|
writable: true,
|
|
320
330
|
value: properties[key],
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
createFinalizeUrlContentError,
|
|
18
18
|
createResolveUrlError,
|
|
19
19
|
createTransformUrlContentError,
|
|
20
|
+
defineNonEnumerableProperties,
|
|
20
21
|
} from "./errors.js";
|
|
21
22
|
import { assertFetchedContentCompliance } from "./fetched_content_compliance.js";
|
|
22
23
|
import { createUrlGraph } from "./url_graph/url_graph.js";
|
|
@@ -426,7 +427,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
426
427
|
urlInfo,
|
|
427
428
|
error,
|
|
428
429
|
});
|
|
429
|
-
urlInfo.error = transformError;
|
|
430
430
|
throw transformError;
|
|
431
431
|
}
|
|
432
432
|
};
|
|
@@ -458,9 +458,6 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
458
458
|
|
|
459
459
|
// urlInfo objects are reused, they must be "reset" before cooking them again
|
|
460
460
|
if (urlInfo.error || urlInfo.content !== undefined) {
|
|
461
|
-
if (urlInfo.isInline) {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
461
|
urlInfo.error = null;
|
|
465
462
|
urlInfo.type = null;
|
|
466
463
|
urlInfo.subtype = null;
|
|
@@ -482,30 +479,46 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
482
479
|
});
|
|
483
480
|
} catch (e) {
|
|
484
481
|
urlInfo.error = e;
|
|
485
|
-
if (
|
|
486
|
-
urlInfo.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
482
|
+
if (urlInfo.isInline) {
|
|
483
|
+
const parentUrlInfo = urlInfo.findParentIfInline();
|
|
484
|
+
parentUrlInfo.error = e;
|
|
485
|
+
}
|
|
486
|
+
let errorWrapperMessage;
|
|
487
|
+
if (e.code === "PARSE_ERROR") {
|
|
488
|
+
errorWrapperMessage =
|
|
489
|
+
e.name === "TRANSFORM_URL_CONTENT_ERROR"
|
|
490
|
+
? e.message
|
|
491
|
+
: `parse error on "${urlInfo.type}"
|
|
495
492
|
${e.trace?.message}
|
|
496
493
|
${e.reason}
|
|
497
494
|
--- declared in ---
|
|
498
|
-
${urlInfo.firstReference.trace.message}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
${urlInfo.firstReference.trace.message}
|
|
504
|
-
|
|
505
|
-
|
|
495
|
+
${urlInfo.firstReference.trace.message}`;
|
|
496
|
+
} else if (e.isJsenvCookingError) {
|
|
497
|
+
errorWrapperMessage = e.message;
|
|
498
|
+
} else {
|
|
499
|
+
errorWrapperMessage = `Error while cooking ${urlInfo.type}
|
|
500
|
+
${urlInfo.firstReference.trace.message}`;
|
|
501
|
+
}
|
|
502
|
+
// if we are cooking inline content during dev it's better not to throw
|
|
503
|
+
// because the main url info (html) is still valid and can be returned to the browser
|
|
504
|
+
if (
|
|
505
|
+
urlInfo.isInline &&
|
|
506
|
+
urlInfo.context.dev &&
|
|
507
|
+
// but if we are explicitely requesting inline content file then we throw
|
|
508
|
+
// to properly send 500 to the browser
|
|
509
|
+
urlInfo.context.reference !== urlInfo.url
|
|
510
|
+
) {
|
|
511
|
+
logger.error(errorWrapperMessage);
|
|
506
512
|
return;
|
|
507
513
|
}
|
|
508
|
-
|
|
514
|
+
if (e.isJsenvCookingError) {
|
|
515
|
+
throw e;
|
|
516
|
+
}
|
|
517
|
+
const error = new Error(errorWrapperMessage, { cause: e });
|
|
518
|
+
defineNonEnumerableProperties(error, {
|
|
519
|
+
__INTERNAL_ERROR__: true,
|
|
520
|
+
});
|
|
521
|
+
throw error;
|
|
509
522
|
}
|
|
510
523
|
}
|
|
511
524
|
|
|
@@ -595,23 +608,6 @@ ${e.stack}`,
|
|
|
595
608
|
return kitchen;
|
|
596
609
|
};
|
|
597
610
|
|
|
598
|
-
// if we are cooking the inline content internally it's better not to throw
|
|
599
|
-
// because the main url info (html) is still valid
|
|
600
|
-
// but if we are explicitely requesting inline content during dev
|
|
601
|
-
// then we should throw
|
|
602
|
-
const errorOnInlineContentCanSkipThrow = (urlInfo) => {
|
|
603
|
-
if (urlInfo.context.build) {
|
|
604
|
-
return true;
|
|
605
|
-
}
|
|
606
|
-
if (
|
|
607
|
-
urlInfo.context.reference &&
|
|
608
|
-
urlInfo.context.reference.url === urlInfo.url
|
|
609
|
-
) {
|
|
610
|
-
return false;
|
|
611
|
-
}
|
|
612
|
-
return true;
|
|
613
|
-
};
|
|
614
|
-
|
|
615
611
|
const debounceCook = (cook) => {
|
|
616
612
|
const pendingDishes = new Map();
|
|
617
613
|
return async (urlInfo, context) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { urlToFilename } from "@jsenv/urls";
|
|
2
|
+
import { defineNonEnumerableProperties } from "../../kitchen/errors.js";
|
|
2
3
|
|
|
3
4
|
export const jsenvPluginDirectoryReferenceEffect = (
|
|
4
5
|
directoryReferenceEffect = "error",
|
|
@@ -53,7 +54,10 @@ export const jsenvPluginDirectoryReferenceEffect = (
|
|
|
53
54
|
}
|
|
54
55
|
if (actionForDirectory === "error") {
|
|
55
56
|
const error = new Error("Reference leads to a directory");
|
|
56
|
-
error
|
|
57
|
+
defineNonEnumerableProperties(error, {
|
|
58
|
+
isJsenvCookingError: true,
|
|
59
|
+
code: "DIRECTORY_REFERENCE_NOT_ALLOWED",
|
|
60
|
+
});
|
|
57
61
|
throw error;
|
|
58
62
|
}
|
|
59
63
|
if (actionForDirectory === "preserve") {
|
|
@@ -274,13 +274,8 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
274
274
|
});
|
|
275
275
|
|
|
276
276
|
actions.push(async () => {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
} catch (e) {
|
|
280
|
-
if (!e || e.code !== "PARSE_ERROR") {
|
|
281
|
-
throw e;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
277
|
+
const inlineUrlInfo = inlineReference.urlInfo;
|
|
278
|
+
await inlineUrlInfo.cook();
|
|
284
279
|
mutations.push(() => {
|
|
285
280
|
if (hotAccept) {
|
|
286
281
|
removeHtmlNodeText(node);
|
|
@@ -288,7 +283,7 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
288
283
|
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
289
284
|
});
|
|
290
285
|
} else {
|
|
291
|
-
setHtmlNodeText(node,
|
|
286
|
+
setHtmlNodeText(node, inlineUrlInfo.content, {
|
|
292
287
|
indentation: false, // indentation would decrease stack trace precision
|
|
293
288
|
});
|
|
294
289
|
setHtmlNodeAttributes(node, {
|
|
@@ -561,7 +556,8 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
561
556
|
}
|
|
562
557
|
mutations.forEach((mutation) => mutation());
|
|
563
558
|
mutations.length = 0;
|
|
564
|
-
|
|
559
|
+
const html = stringifyHtmlAst(htmlAst);
|
|
560
|
+
return html;
|
|
565
561
|
} catch (e) {
|
|
566
562
|
importmapLoaded();
|
|
567
563
|
throw e;
|
|
@@ -45,8 +45,12 @@ const jsenvPluginInlineContentFetcher = () => {
|
|
|
45
45
|
// when updating the file, first reference is the previous version
|
|
46
46
|
// - we cannot use urlInfo.lastReference because it can be the reference created by "http_request"
|
|
47
47
|
let lastInlineReference;
|
|
48
|
+
let originalContent = urlInfo.originalContent;
|
|
48
49
|
for (const reference of urlInfo.referenceFromOthersSet) {
|
|
49
50
|
if (reference.isInline) {
|
|
51
|
+
if (originalContent === undefined) {
|
|
52
|
+
originalContent = reference.content;
|
|
53
|
+
}
|
|
50
54
|
lastInlineReference = reference;
|
|
51
55
|
}
|
|
52
56
|
}
|
|
@@ -61,8 +65,17 @@ const jsenvPluginInlineContentFetcher = () => {
|
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
return {
|
|
64
|
-
originalContent
|
|
65
|
-
content:
|
|
68
|
+
originalContent,
|
|
69
|
+
content:
|
|
70
|
+
// we must favor original content to re-apply the same plugin logic
|
|
71
|
+
// so that the same references are generated
|
|
72
|
+
// without this we would try to resolve references like
|
|
73
|
+
// "/node_modules/package/file.js" instead of "package/file.js"
|
|
74
|
+
// meaning we would not create the implicit dependency to package.json
|
|
75
|
+
// resulting in a reload of the browser (as implicit reference to package.json is gone)
|
|
76
|
+
originalContent === undefined
|
|
77
|
+
? lastInlineReference.content
|
|
78
|
+
: originalContent,
|
|
66
79
|
contentType: lastInlineReference.contentType,
|
|
67
80
|
};
|
|
68
81
|
},
|
|
@@ -53,47 +53,46 @@ export const createNodeEsmResolver = ({
|
|
|
53
53
|
specifier: reference.specifier,
|
|
54
54
|
preservesSymlink,
|
|
55
55
|
});
|
|
56
|
-
if (ownerUrlInfo.context.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
56
|
+
if (ownerUrlInfo.context.build) {
|
|
57
|
+
return url;
|
|
58
|
+
}
|
|
59
|
+
const dependsOnPackageJson =
|
|
60
|
+
type !== "relative_specifier" &&
|
|
61
|
+
type !== "absolute_specifier" &&
|
|
62
|
+
type !== "node_builtin_specifier";
|
|
63
|
+
if (dependsOnPackageJson) {
|
|
64
|
+
// this reference depends on package.json and node_modules
|
|
65
|
+
// to be resolved. Each file using this specifier
|
|
66
|
+
// must be invalidated when corresponding package.json changes
|
|
67
|
+
addRelationshipWithPackageJson({
|
|
68
|
+
reference,
|
|
69
|
+
packageJsonUrl: `${packageDirectoryUrl}package.json`,
|
|
70
|
+
field: type.startsWith("field:")
|
|
71
|
+
? `#${type.slice("field:".length)}`
|
|
72
|
+
: "",
|
|
73
|
+
});
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
reference.version = packageVersion;
|
|
75
|
+
// without this check a file inside a project without package.json
|
|
76
|
+
// could be considered as a node module if there is a ancestor package.json
|
|
77
|
+
// but we want to version only node modules
|
|
78
|
+
if (url.includes("/node_modules/")) {
|
|
79
|
+
const packageDirectoryUrl = defaultLookupPackageScope(url);
|
|
80
|
+
if (
|
|
81
|
+
packageDirectoryUrl &&
|
|
82
|
+
packageDirectoryUrl !== ownerUrlInfo.context.rootDirectoryUrl
|
|
83
|
+
) {
|
|
84
|
+
const packageVersion =
|
|
85
|
+
defaultReadPackageJson(packageDirectoryUrl).version;
|
|
86
|
+
// package version can be null, see https://github.com/babel/babel/blob/2ce56e832c2dd7a7ed92c89028ba929f874c2f5c/packages/babel-runtime/helpers/esm/package.json#L2
|
|
87
|
+
if (packageVersion) {
|
|
88
|
+
addRelationshipWithPackageJson({
|
|
89
|
+
reference,
|
|
90
|
+
packageJsonUrl: `${packageDirectoryUrl}package.json`,
|
|
91
|
+
field: "version",
|
|
92
|
+
hasVersioningEffect: true,
|
|
93
|
+
});
|
|
96
94
|
}
|
|
95
|
+
reference.version = packageVersion;
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
98
|
return url;
|