@jsenv/core 39.5.23 → 39.5.25
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/jsenv_core.js +150 -40
- package/package.json +9 -9
- package/src/kitchen/fetched_content_compliance.js +5 -4
- package/src/kitchen/kitchen.js +11 -10
- package/src/kitchen/url_graph/url_graph.js +1 -0
- package/src/plugins/html_syntax_error_fallback/jsenv_plugin_html_syntax_error_fallback.js +6 -2
- package/src/plugins/protocol_file/jsenv_plugin_fs_redirection.js +3 -2
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +8 -4
package/dist/jsenv_core.js
CHANGED
|
@@ -3,7 +3,7 @@ import os, { networkInterfaces } from "node:os";
|
|
|
3
3
|
import tty from "node:tty";
|
|
4
4
|
import stringWidth from "string-width";
|
|
5
5
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
6
|
-
import { readdir, chmod, stat, lstat, promises, readFileSync, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, watch, readdirSync,
|
|
6
|
+
import { readdir, chmod, stat, lstat, chmodSync, statSync, lstatSync, promises, readFileSync, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, watch, readdirSync, createReadStream, readFile, existsSync, realpathSync } from "node:fs";
|
|
7
7
|
import { extname } from "node:path";
|
|
8
8
|
import crypto, { createHash } from "node:crypto";
|
|
9
9
|
import cluster from "node:cluster";
|
|
@@ -988,7 +988,7 @@ platform === 'Android'
|
|
|
988
988
|
const ESC = '\u001B[';
|
|
989
989
|
|
|
990
990
|
!isBrowser && process$1.env.TERM_PROGRAM === 'Apple_Terminal';
|
|
991
|
-
const isWindows$
|
|
991
|
+
const isWindows$4 = !isBrowser && process$1.platform === 'win32';
|
|
992
992
|
|
|
993
993
|
isBrowser ? () => {
|
|
994
994
|
throw new Error('`process.cwd()` only works in Node.js, not the browser.');
|
|
@@ -1014,7 +1014,7 @@ const eraseLines = count => {
|
|
|
1014
1014
|
const eraseLine = ESC + '2K';
|
|
1015
1015
|
const eraseScreen = ESC + '2J';
|
|
1016
1016
|
|
|
1017
|
-
const clearTerminal = isWindows$
|
|
1017
|
+
const clearTerminal = isWindows$4
|
|
1018
1018
|
? `${eraseScreen}${ESC}0f`
|
|
1019
1019
|
// 1. Erases the screen (Only done in case `2` is not supported)
|
|
1020
1020
|
// 2. Erases the whole screen including scrollback buffer
|
|
@@ -1808,13 +1808,21 @@ const urlIsInsideOf = (url, otherUrl) => {
|
|
|
1808
1808
|
};
|
|
1809
1809
|
|
|
1810
1810
|
const urlToFileSystemPath = (url) => {
|
|
1811
|
-
|
|
1812
|
-
|
|
1811
|
+
const urlObject = new URL(url);
|
|
1812
|
+
let urlString;
|
|
1813
|
+
if (urlObject.hash) {
|
|
1814
|
+
const origin =
|
|
1815
|
+
urlObject.protocol === "file:" ? "file://" : urlObject.origin;
|
|
1816
|
+
urlString = `${origin}${urlObject.pathname}${urlObject.search}%23${urlObject.hash.slice(1)}`;
|
|
1817
|
+
} else {
|
|
1818
|
+
urlString = urlObject.href;
|
|
1819
|
+
}
|
|
1820
|
+
const fileSystemPath = fileURLToPath(urlString);
|
|
1821
|
+
if (fileSystemPath[fileSystemPath.length - 1] === "/") {
|
|
1813
1822
|
// remove trailing / so that nodejs path becomes predictable otherwise it logs
|
|
1814
1823
|
// the trailing slash on linux but does not on windows
|
|
1815
|
-
|
|
1824
|
+
return fileSystemPath.slice(0, -1);
|
|
1816
1825
|
}
|
|
1817
|
-
const fileSystemPath = fileURLToPath(urlString);
|
|
1818
1826
|
return fileSystemPath;
|
|
1819
1827
|
};
|
|
1820
1828
|
|
|
@@ -1977,7 +1985,7 @@ const comparePathnames = (leftPathame, rightPathname) => {
|
|
|
1977
1985
|
return 0;
|
|
1978
1986
|
};
|
|
1979
1987
|
|
|
1980
|
-
const isWindows$
|
|
1988
|
+
const isWindows$3 = process.platform === "win32";
|
|
1981
1989
|
const baseUrlFallback = fileSystemPathToUrl$1(process.cwd());
|
|
1982
1990
|
|
|
1983
1991
|
/**
|
|
@@ -2000,7 +2008,7 @@ const ensureWindowsDriveLetter = (url, baseUrl) => {
|
|
|
2000
2008
|
throw new Error(`absolute url expect but got ${url}`);
|
|
2001
2009
|
}
|
|
2002
2010
|
|
|
2003
|
-
if (!isWindows$
|
|
2011
|
+
if (!isWindows$3) {
|
|
2004
2012
|
return url;
|
|
2005
2013
|
}
|
|
2006
2014
|
|
|
@@ -3165,7 +3173,7 @@ const writeEntryPermissions = async (source, permissions) => {
|
|
|
3165
3173
|
*/
|
|
3166
3174
|
|
|
3167
3175
|
|
|
3168
|
-
const isWindows$
|
|
3176
|
+
const isWindows$2 = process.platform === "win32";
|
|
3169
3177
|
|
|
3170
3178
|
const readEntryStat = async (
|
|
3171
3179
|
source,
|
|
@@ -3185,7 +3193,7 @@ const readEntryStat = async (
|
|
|
3185
3193
|
return readStat(sourcePath, {
|
|
3186
3194
|
followLink,
|
|
3187
3195
|
...handleNotFoundOption,
|
|
3188
|
-
...(isWindows$
|
|
3196
|
+
...(isWindows$2
|
|
3189
3197
|
? {
|
|
3190
3198
|
// Windows can EPERM on stat
|
|
3191
3199
|
handlePermissionDeniedError: async (error) => {
|
|
@@ -3250,13 +3258,104 @@ const readStat = (
|
|
|
3250
3258
|
});
|
|
3251
3259
|
};
|
|
3252
3260
|
|
|
3261
|
+
const writeEntryPermissionsSync = (source, permissions) => {
|
|
3262
|
+
const sourceUrl = assertAndNormalizeFileUrl(source);
|
|
3263
|
+
|
|
3264
|
+
let binaryFlags;
|
|
3265
|
+
{
|
|
3266
|
+
binaryFlags = permissions;
|
|
3267
|
+
}
|
|
3268
|
+
|
|
3269
|
+
chmodSync(new URL(sourceUrl), binaryFlags);
|
|
3270
|
+
};
|
|
3271
|
+
|
|
3253
3272
|
/*
|
|
3254
3273
|
* - stats object documentation on Node.js
|
|
3255
3274
|
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
3256
3275
|
*/
|
|
3257
3276
|
|
|
3258
3277
|
|
|
3259
|
-
process.platform === "win32";
|
|
3278
|
+
const isWindows$1 = process.platform === "win32";
|
|
3279
|
+
|
|
3280
|
+
const readEntryStatSync = (
|
|
3281
|
+
source,
|
|
3282
|
+
{ nullIfNotFound = false, followLink = true } = {},
|
|
3283
|
+
) => {
|
|
3284
|
+
let sourceUrl = assertAndNormalizeFileUrl(source);
|
|
3285
|
+
if (sourceUrl.endsWith("/")) sourceUrl = sourceUrl.slice(0, -1);
|
|
3286
|
+
|
|
3287
|
+
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
3288
|
+
|
|
3289
|
+
const handleNotFoundOption = nullIfNotFound
|
|
3290
|
+
? {
|
|
3291
|
+
handleNotFoundError: () => null,
|
|
3292
|
+
}
|
|
3293
|
+
: {};
|
|
3294
|
+
|
|
3295
|
+
return statSyncNaive(sourcePath, {
|
|
3296
|
+
followLink,
|
|
3297
|
+
...handleNotFoundOption,
|
|
3298
|
+
...(isWindows$1
|
|
3299
|
+
? {
|
|
3300
|
+
// Windows can EPERM on stat
|
|
3301
|
+
handlePermissionDeniedError: (error) => {
|
|
3302
|
+
console.error(
|
|
3303
|
+
`trying to fix windows EPERM after stats on ${sourcePath}`,
|
|
3304
|
+
);
|
|
3305
|
+
|
|
3306
|
+
try {
|
|
3307
|
+
// unfortunately it means we mutate the permissions
|
|
3308
|
+
// without being able to restore them to the previous value
|
|
3309
|
+
// (because reading current permission would also throw)
|
|
3310
|
+
writeEntryPermissionsSync(sourceUrl, 0o666);
|
|
3311
|
+
const stats = statSyncNaive(sourcePath, {
|
|
3312
|
+
followLink,
|
|
3313
|
+
...handleNotFoundOption,
|
|
3314
|
+
// could not fix the permission error, give up and throw original error
|
|
3315
|
+
handlePermissionDeniedError: () => {
|
|
3316
|
+
console.error(`still got EPERM after stats on ${sourcePath}`);
|
|
3317
|
+
throw error;
|
|
3318
|
+
},
|
|
3319
|
+
});
|
|
3320
|
+
return stats;
|
|
3321
|
+
} catch (e) {
|
|
3322
|
+
console.error(
|
|
3323
|
+
`error while trying to fix windows EPERM after stats on ${sourcePath}: ${e.stack}`,
|
|
3324
|
+
);
|
|
3325
|
+
throw error;
|
|
3326
|
+
}
|
|
3327
|
+
},
|
|
3328
|
+
}
|
|
3329
|
+
: {}),
|
|
3330
|
+
});
|
|
3331
|
+
};
|
|
3332
|
+
|
|
3333
|
+
const statSyncNaive = (
|
|
3334
|
+
sourcePath,
|
|
3335
|
+
{
|
|
3336
|
+
followLink,
|
|
3337
|
+
handleNotFoundError = null,
|
|
3338
|
+
handlePermissionDeniedError = null,
|
|
3339
|
+
} = {},
|
|
3340
|
+
) => {
|
|
3341
|
+
const nodeMethod = followLink ? statSync : lstatSync;
|
|
3342
|
+
|
|
3343
|
+
try {
|
|
3344
|
+
const stats = nodeMethod(sourcePath);
|
|
3345
|
+
return stats;
|
|
3346
|
+
} catch (error) {
|
|
3347
|
+
if (handleNotFoundError && error.code === "ENOENT") {
|
|
3348
|
+
return handleNotFoundError(error);
|
|
3349
|
+
}
|
|
3350
|
+
if (
|
|
3351
|
+
handlePermissionDeniedError &&
|
|
3352
|
+
(error.code === "EPERM" || error.code === "EACCES")
|
|
3353
|
+
) {
|
|
3354
|
+
return handlePermissionDeniedError(error);
|
|
3355
|
+
}
|
|
3356
|
+
throw error;
|
|
3357
|
+
}
|
|
3358
|
+
};
|
|
3260
3359
|
|
|
3261
3360
|
const statsToType = (stats) => {
|
|
3262
3361
|
if (stats.isFile()) return "file";
|
|
@@ -3958,7 +4057,7 @@ const registerDirectoryLifecycle = (
|
|
|
3958
4057
|
try {
|
|
3959
4058
|
const relativeUrl = urlToRelativeUrl(url, source);
|
|
3960
4059
|
const previousInfo = infoMap.get(relativeUrl);
|
|
3961
|
-
const stat =
|
|
4060
|
+
const stat = readEntryStatSync(new URL(url));
|
|
3962
4061
|
const type = statsToType(stat);
|
|
3963
4062
|
const patternValue = previousInfo
|
|
3964
4063
|
? previousInfo.patternValue
|
|
@@ -4035,7 +4134,7 @@ const registerDirectoryLifecycle = (
|
|
|
4035
4134
|
const removedEntryRelativeUrl = relativeUrlCandidateArray.find(
|
|
4036
4135
|
(relativeUrlCandidate) => {
|
|
4037
4136
|
try {
|
|
4038
|
-
|
|
4137
|
+
readEntryStatSync(new URL(relativeUrlCandidate, sourceUrl));
|
|
4039
4138
|
return false;
|
|
4040
4139
|
} catch (e) {
|
|
4041
4140
|
if (e.code === "ENOENT") {
|
|
@@ -4186,8 +4285,8 @@ const registerDirectoryLifecycle = (
|
|
|
4186
4285
|
}
|
|
4187
4286
|
};
|
|
4188
4287
|
const handleEntryUpdated = (entryInfo) => {
|
|
4189
|
-
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
4190
4288
|
if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
|
|
4289
|
+
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
4191
4290
|
updated({
|
|
4192
4291
|
relativeUrl: entryInfo.relativeUrl,
|
|
4193
4292
|
type: entryInfo.type,
|
|
@@ -8686,7 +8785,7 @@ const bundleCss = async (cssUrlInfos) => {
|
|
|
8686
8785
|
},
|
|
8687
8786
|
resolve(specifier, from) {
|
|
8688
8787
|
const fileUrlObject = new URL(specifier, pathToFileURL(from));
|
|
8689
|
-
const filePath =
|
|
8788
|
+
const filePath = urlToFileSystemPath(fileUrlObject);
|
|
8690
8789
|
return filePath;
|
|
8691
8790
|
},
|
|
8692
8791
|
},
|
|
@@ -8755,7 +8854,7 @@ const minifyCss = async (cssUrlInfo) => {
|
|
|
8755
8854
|
|
|
8756
8855
|
const targets = runtimeCompatToTargets$1(cssUrlInfo.context.runtimeCompat);
|
|
8757
8856
|
const { code, map } = transform({
|
|
8758
|
-
filename:
|
|
8857
|
+
filename: urlToFileSystemPath(cssUrlInfo.originalUrl),
|
|
8759
8858
|
code: Buffer.from(cssUrlInfo.content),
|
|
8760
8859
|
targets,
|
|
8761
8860
|
minify: true,
|
|
@@ -10601,7 +10700,7 @@ const applyCssTranspilation = async ({
|
|
|
10601
10700
|
const { transform } = await import("lightningcss");
|
|
10602
10701
|
const targets = runtimeCompatToTargets(runtimeCompat);
|
|
10603
10702
|
const { code, map } = transform({
|
|
10604
|
-
filename:
|
|
10703
|
+
filename: urlToFileSystemPath(inputUrl),
|
|
10605
10704
|
code: Buffer.from(input),
|
|
10606
10705
|
targets,
|
|
10607
10706
|
minify: false,
|
|
@@ -10875,7 +10974,7 @@ const jsenvPluginImportAttributes = ({
|
|
|
10875
10974
|
const originalUrlInfo = urlInfo.getWithoutSearchParam(
|
|
10876
10975
|
`as_${type}_module`,
|
|
10877
10976
|
{
|
|
10878
|
-
expectedType:
|
|
10977
|
+
expectedType: type,
|
|
10879
10978
|
},
|
|
10880
10979
|
);
|
|
10881
10980
|
if (!originalUrlInfo) {
|
|
@@ -11172,6 +11271,10 @@ const generateHtmlForSyntaxError = (
|
|
|
11172
11271
|
const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
|
|
11173
11272
|
const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
|
|
11174
11273
|
const { line, column } = htmlSyntaxError;
|
|
11274
|
+
if (htmlUrl.startsWith(jsenvCoreDirectoryUrl.href)) {
|
|
11275
|
+
htmlUrl = urlToRelativeUrl(htmlUrl, jsenvCoreDirectoryUrl);
|
|
11276
|
+
htmlUrl = `@jsenv/core/${htmlUrl}`;
|
|
11277
|
+
}
|
|
11175
11278
|
const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
|
|
11176
11279
|
const replacers = {
|
|
11177
11280
|
fileRelativeUrl: htmlRelativeUrl,
|
|
@@ -12046,17 +12149,18 @@ const isResponseEligibleForIntegrityValidation = (response) => {
|
|
|
12046
12149
|
};
|
|
12047
12150
|
|
|
12048
12151
|
const assertFetchedContentCompliance = ({ urlInfo, content }) => {
|
|
12152
|
+
if (urlInfo.status === 404) {
|
|
12153
|
+
return;
|
|
12154
|
+
}
|
|
12049
12155
|
const { expectedContentType } = urlInfo.firstReference;
|
|
12050
12156
|
if (expectedContentType && urlInfo.contentType !== expectedContentType) {
|
|
12051
12157
|
throw new Error(
|
|
12052
|
-
`
|
|
12158
|
+
`content-type must be "${expectedContentType}", got "${urlInfo.contentType}`,
|
|
12053
12159
|
);
|
|
12054
12160
|
}
|
|
12055
12161
|
const { expectedType } = urlInfo.firstReference;
|
|
12056
12162
|
if (expectedType && urlInfo.type !== expectedType) {
|
|
12057
|
-
throw new Error(
|
|
12058
|
-
`Unexpected type on url: "${expectedType}" was expect but got "${urlInfo.type}"`,
|
|
12059
|
-
);
|
|
12163
|
+
throw new Error(`type must be "${expectedType}", got "${urlInfo.type}"`);
|
|
12060
12164
|
}
|
|
12061
12165
|
const { integrity } = urlInfo.firstReference;
|
|
12062
12166
|
if (integrity) {
|
|
@@ -13433,6 +13537,7 @@ const createUrlInfo = (url, context) => {
|
|
|
13433
13537
|
jsQuote: null, // maybe move to inlineUrlSite?
|
|
13434
13538
|
|
|
13435
13539
|
timing: {},
|
|
13540
|
+
status: 200,
|
|
13436
13541
|
headers: {},
|
|
13437
13542
|
debug: false,
|
|
13438
13543
|
};
|
|
@@ -14500,21 +14605,16 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
14500
14605
|
body,
|
|
14501
14606
|
isEntryPoint,
|
|
14502
14607
|
} = fetchUrlContentReturnValue;
|
|
14503
|
-
if (status !== 200) {
|
|
14504
|
-
throw new Error(`unexpected status, ${status}`);
|
|
14505
|
-
}
|
|
14506
14608
|
if (content === undefined) {
|
|
14507
14609
|
content = body;
|
|
14508
14610
|
}
|
|
14509
14611
|
if (contentType === undefined) {
|
|
14510
14612
|
contentType = headers["content-type"] || "application/octet-stream";
|
|
14511
14613
|
}
|
|
14614
|
+
urlInfo.status = status;
|
|
14512
14615
|
urlInfo.contentType = contentType;
|
|
14513
14616
|
urlInfo.headers = headers;
|
|
14514
|
-
urlInfo.type =
|
|
14515
|
-
type ||
|
|
14516
|
-
urlInfo.firstReference.expectedType ||
|
|
14517
|
-
inferUrlInfoType(urlInfo);
|
|
14617
|
+
urlInfo.type = type || inferUrlInfoType(urlInfo);
|
|
14518
14618
|
urlInfo.subtype =
|
|
14519
14619
|
subtype ||
|
|
14520
14620
|
urlInfo.firstReference.expectedSubtype ||
|
|
@@ -14838,10 +14938,11 @@ const memoizeIsSupported = (runtimeCompat) => {
|
|
|
14838
14938
|
|
|
14839
14939
|
const inferUrlInfoType = (urlInfo) => {
|
|
14840
14940
|
const { type, typeHint } = urlInfo;
|
|
14941
|
+
const { contentType } = urlInfo;
|
|
14942
|
+
const { expectedType } = urlInfo.firstReference;
|
|
14841
14943
|
if (type === "sourcemap" || typeHint === "sourcemap") {
|
|
14842
14944
|
return "sourcemap";
|
|
14843
14945
|
}
|
|
14844
|
-
const { contentType } = urlInfo;
|
|
14845
14946
|
if (contentType === "text/html") {
|
|
14846
14947
|
return "html";
|
|
14847
14948
|
}
|
|
@@ -14849,7 +14950,12 @@ const inferUrlInfoType = (urlInfo) => {
|
|
|
14849
14950
|
return "css";
|
|
14850
14951
|
}
|
|
14851
14952
|
if (contentType === "text/javascript") {
|
|
14852
|
-
if (
|
|
14953
|
+
if (expectedType === "js_classic") {
|
|
14954
|
+
return "js_classic";
|
|
14955
|
+
}
|
|
14956
|
+
if (typeHint === "js_classic") {
|
|
14957
|
+
return "js_classic";
|
|
14958
|
+
}
|
|
14853
14959
|
return "js_module";
|
|
14854
14960
|
}
|
|
14855
14961
|
if (contentType === "application/importmap+json") {
|
|
@@ -14867,7 +14973,7 @@ const inferUrlInfoType = (urlInfo) => {
|
|
|
14867
14973
|
if (CONTENT_TYPE.isTextual(contentType)) {
|
|
14868
14974
|
return "text";
|
|
14869
14975
|
}
|
|
14870
|
-
return "other";
|
|
14976
|
+
return expectedType || "other";
|
|
14871
14977
|
};
|
|
14872
14978
|
|
|
14873
14979
|
const createUrlGraphSummary = (
|
|
@@ -18269,7 +18375,7 @@ const applyFileSystemMagicResolution = (
|
|
|
18269
18375
|
|
|
18270
18376
|
if (fileStat === undefined) {
|
|
18271
18377
|
try {
|
|
18272
|
-
fileStat =
|
|
18378
|
+
fileStat = readEntryStatSync(new URL(fileUrl));
|
|
18273
18379
|
} catch (e) {
|
|
18274
18380
|
if (e.code === "ENOENT") {
|
|
18275
18381
|
result.lastENOENTError = e;
|
|
@@ -18311,7 +18417,7 @@ const applyFileSystemMagicResolution = (
|
|
|
18311
18417
|
const urlCandidate = `${parentUrl}${urlFilename}${extensionToTry}`;
|
|
18312
18418
|
let stat;
|
|
18313
18419
|
try {
|
|
18314
|
-
stat =
|
|
18420
|
+
stat = readEntryStatSync(new URL(urlCandidate));
|
|
18315
18421
|
} catch (e) {
|
|
18316
18422
|
if (e.code === "ENOENT") {
|
|
18317
18423
|
stat = null;
|
|
@@ -18672,7 +18778,7 @@ const jsenvPluginFsRedirection = ({
|
|
|
18672
18778
|
const urlObject = new URL(reference.url);
|
|
18673
18779
|
let stat;
|
|
18674
18780
|
try {
|
|
18675
|
-
stat =
|
|
18781
|
+
stat = readEntryStatSync(urlObject);
|
|
18676
18782
|
} catch (e) {
|
|
18677
18783
|
if (e.code === "ENOENT") {
|
|
18678
18784
|
stat = null;
|
|
@@ -18852,10 +18958,13 @@ const jsenvPluginProtocolFile = ({
|
|
|
18852
18958
|
};
|
|
18853
18959
|
}
|
|
18854
18960
|
const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url);
|
|
18855
|
-
|
|
18961
|
+
const request = urlInfo.context.request;
|
|
18962
|
+
if (request && request.headers["sec-fetch-dest"] === "document") {
|
|
18856
18963
|
try {
|
|
18857
18964
|
const fileBuffer = readFileSync(urlObject);
|
|
18858
|
-
const content =
|
|
18965
|
+
const content = CONTENT_TYPE.isTextual(contentType)
|
|
18966
|
+
? String(fileBuffer)
|
|
18967
|
+
: fileBuffer;
|
|
18859
18968
|
return {
|
|
18860
18969
|
content,
|
|
18861
18970
|
contentType,
|
|
@@ -18872,7 +18981,7 @@ const jsenvPluginProtocolFile = ({
|
|
|
18872
18981
|
const parentDirectoryContentArray = readdirSync(
|
|
18873
18982
|
new URL(parentDirectoryUrl),
|
|
18874
18983
|
);
|
|
18875
|
-
const html =
|
|
18984
|
+
const html = generateHtmlForENOENT(
|
|
18876
18985
|
urlInfo.url,
|
|
18877
18986
|
parentDirectoryContentArray,
|
|
18878
18987
|
parentDirectoryUrl,
|
|
@@ -18880,6 +18989,7 @@ const jsenvPluginProtocolFile = ({
|
|
|
18880
18989
|
directoryListingUrlMocks,
|
|
18881
18990
|
);
|
|
18882
18991
|
return {
|
|
18992
|
+
status: 404,
|
|
18883
18993
|
contentType: "text/html",
|
|
18884
18994
|
content: html,
|
|
18885
18995
|
headers: {
|
|
@@ -18925,7 +19035,7 @@ const generateHtmlForDirectory = (
|
|
|
18925
19035
|
const html = replacePlaceholders$1(htmlForDirectory, replacers);
|
|
18926
19036
|
return html;
|
|
18927
19037
|
};
|
|
18928
|
-
const
|
|
19038
|
+
const generateHtmlForENOENT = (
|
|
18929
19039
|
url,
|
|
18930
19040
|
parentDirectoryContentArray,
|
|
18931
19041
|
parentDirectoryUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "39.5.
|
|
3
|
+
"version": "39.5.25",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -69,22 +69,22 @@
|
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
71
71
|
"@jsenv/abort": "4.3.0",
|
|
72
|
-
"@jsenv/ast": "6.3.
|
|
73
|
-
"@jsenv/filesystem": "4.10.
|
|
72
|
+
"@jsenv/ast": "6.3.6",
|
|
73
|
+
"@jsenv/filesystem": "4.10.12",
|
|
74
74
|
"@jsenv/humanize": "1.2.8",
|
|
75
75
|
"@jsenv/importmap": "1.2.1",
|
|
76
76
|
"@jsenv/integrity": "0.0.2",
|
|
77
|
-
"@jsenv/js-module-fallback": "1.3.
|
|
77
|
+
"@jsenv/js-module-fallback": "1.3.50",
|
|
78
78
|
"@jsenv/node-esm-resolution": "1.0.6",
|
|
79
|
-
"@jsenv/plugin-bundling": "2.7.
|
|
79
|
+
"@jsenv/plugin-bundling": "2.7.17",
|
|
80
80
|
"@jsenv/plugin-minification": "1.5.10",
|
|
81
|
-
"@jsenv/plugin-supervisor": "1.5.
|
|
82
|
-
"@jsenv/plugin-transpilation": "1.4.
|
|
81
|
+
"@jsenv/plugin-supervisor": "1.5.29",
|
|
82
|
+
"@jsenv/plugin-transpilation": "1.4.85",
|
|
83
83
|
"@jsenv/runtime-compat": "1.3.1",
|
|
84
84
|
"@jsenv/server": "15.3.3",
|
|
85
|
-
"@jsenv/sourcemap": "1.2.
|
|
85
|
+
"@jsenv/sourcemap": "1.2.26",
|
|
86
86
|
"@jsenv/url-meta": "8.5.2",
|
|
87
|
-
"@jsenv/urls": "2.5.
|
|
87
|
+
"@jsenv/urls": "2.5.3",
|
|
88
88
|
"@jsenv/utils": "2.1.2",
|
|
89
89
|
"string-width": "7.2.0"
|
|
90
90
|
},
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { validateResponseIntegrity } from "@jsenv/integrity";
|
|
2
2
|
|
|
3
3
|
export const assertFetchedContentCompliance = ({ urlInfo, content }) => {
|
|
4
|
+
if (urlInfo.status === 404) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
4
7
|
const { expectedContentType } = urlInfo.firstReference;
|
|
5
8
|
if (expectedContentType && urlInfo.contentType !== expectedContentType) {
|
|
6
9
|
throw new Error(
|
|
7
|
-
`
|
|
10
|
+
`content-type must be "${expectedContentType}", got "${urlInfo.contentType}`,
|
|
8
11
|
);
|
|
9
12
|
}
|
|
10
13
|
const { expectedType } = urlInfo.firstReference;
|
|
11
14
|
if (expectedType && urlInfo.type !== expectedType) {
|
|
12
|
-
throw new Error(
|
|
13
|
-
`Unexpected type on url: "${expectedType}" was expect but got "${urlInfo.type}"`,
|
|
14
|
-
);
|
|
15
|
+
throw new Error(`type must be "${expectedType}", got "${urlInfo.type}"`);
|
|
15
16
|
}
|
|
16
17
|
const { integrity } = urlInfo.firstReference;
|
|
17
18
|
if (integrity) {
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -342,21 +342,16 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
342
342
|
body,
|
|
343
343
|
isEntryPoint,
|
|
344
344
|
} = fetchUrlContentReturnValue;
|
|
345
|
-
if (status !== 200) {
|
|
346
|
-
throw new Error(`unexpected status, ${status}`);
|
|
347
|
-
}
|
|
348
345
|
if (content === undefined) {
|
|
349
346
|
content = body;
|
|
350
347
|
}
|
|
351
348
|
if (contentType === undefined) {
|
|
352
349
|
contentType = headers["content-type"] || "application/octet-stream";
|
|
353
350
|
}
|
|
351
|
+
urlInfo.status = status;
|
|
354
352
|
urlInfo.contentType = contentType;
|
|
355
353
|
urlInfo.headers = headers;
|
|
356
|
-
urlInfo.type =
|
|
357
|
-
type ||
|
|
358
|
-
urlInfo.firstReference.expectedType ||
|
|
359
|
-
inferUrlInfoType(urlInfo);
|
|
354
|
+
urlInfo.type = type || inferUrlInfoType(urlInfo);
|
|
360
355
|
urlInfo.subtype =
|
|
361
356
|
subtype ||
|
|
362
357
|
urlInfo.firstReference.expectedSubtype ||
|
|
@@ -680,10 +675,11 @@ const memoizeIsSupported = (runtimeCompat) => {
|
|
|
680
675
|
|
|
681
676
|
const inferUrlInfoType = (urlInfo) => {
|
|
682
677
|
const { type, typeHint } = urlInfo;
|
|
678
|
+
const { contentType } = urlInfo;
|
|
679
|
+
const { expectedType } = urlInfo.firstReference;
|
|
683
680
|
if (type === "sourcemap" || typeHint === "sourcemap") {
|
|
684
681
|
return "sourcemap";
|
|
685
682
|
}
|
|
686
|
-
const { contentType } = urlInfo;
|
|
687
683
|
if (contentType === "text/html") {
|
|
688
684
|
return "html";
|
|
689
685
|
}
|
|
@@ -691,7 +687,12 @@ const inferUrlInfoType = (urlInfo) => {
|
|
|
691
687
|
return "css";
|
|
692
688
|
}
|
|
693
689
|
if (contentType === "text/javascript") {
|
|
694
|
-
if (
|
|
690
|
+
if (expectedType === "js_classic") {
|
|
691
|
+
return "js_classic";
|
|
692
|
+
}
|
|
693
|
+
if (typeHint === "js_classic") {
|
|
694
|
+
return "js_classic";
|
|
695
|
+
}
|
|
695
696
|
return "js_module";
|
|
696
697
|
}
|
|
697
698
|
if (contentType === "application/importmap+json") {
|
|
@@ -709,5 +710,5 @@ const inferUrlInfoType = (urlInfo) => {
|
|
|
709
710
|
if (CONTENT_TYPE.isTextual(contentType)) {
|
|
710
711
|
return "text";
|
|
711
712
|
}
|
|
712
|
-
return "other";
|
|
713
|
+
return expectedType || "other";
|
|
713
714
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseHtml } from "@jsenv/ast";
|
|
2
|
+
import { generateContentFrame } from "@jsenv/humanize";
|
|
2
3
|
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
3
4
|
import { readFileSync } from "node:fs";
|
|
4
|
-
|
|
5
|
-
import { generateContentFrame } from "@jsenv/humanize";
|
|
5
|
+
import { jsenvCoreDirectoryUrl } from "../../jsenv_core_directory_url.js";
|
|
6
6
|
|
|
7
7
|
export const jsenvPluginHtmlSyntaxErrorFallback = () => {
|
|
8
8
|
const htmlSyntaxErrorFileUrl = new URL(
|
|
@@ -58,6 +58,10 @@ const generateHtmlForSyntaxError = (
|
|
|
58
58
|
const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
|
|
59
59
|
const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
|
|
60
60
|
const { line, column } = htmlSyntaxError;
|
|
61
|
+
if (htmlUrl.startsWith(jsenvCoreDirectoryUrl.href)) {
|
|
62
|
+
htmlUrl = urlToRelativeUrl(htmlUrl, jsenvCoreDirectoryUrl);
|
|
63
|
+
htmlUrl = `@jsenv/core/${htmlUrl}`;
|
|
64
|
+
}
|
|
61
65
|
const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
|
|
62
66
|
const replacers = {
|
|
63
67
|
fileRelativeUrl: htmlRelativeUrl,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { readEntryStatSync } from "@jsenv/filesystem";
|
|
1
2
|
import {
|
|
2
3
|
applyFileSystemMagicResolution,
|
|
3
4
|
getExtensionsToTry,
|
|
4
5
|
} from "@jsenv/node-esm-resolution";
|
|
5
|
-
import { realpathSync
|
|
6
|
+
import { realpathSync } from "node:fs";
|
|
6
7
|
import { pathToFileURL } from "node:url";
|
|
7
8
|
|
|
8
9
|
export const jsenvPluginFsRedirection = ({
|
|
@@ -39,7 +40,7 @@ export const jsenvPluginFsRedirection = ({
|
|
|
39
40
|
const urlObject = new URL(reference.url);
|
|
40
41
|
let stat;
|
|
41
42
|
try {
|
|
42
|
-
stat =
|
|
43
|
+
stat = readEntryStatSync(urlObject);
|
|
43
44
|
} catch (e) {
|
|
44
45
|
if (e.code === "ENOENT") {
|
|
45
46
|
stat = null;
|
|
@@ -118,10 +118,13 @@ export const jsenvPluginProtocolFile = ({
|
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url);
|
|
121
|
-
|
|
121
|
+
const request = urlInfo.context.request;
|
|
122
|
+
if (request && request.headers["sec-fetch-dest"] === "document") {
|
|
122
123
|
try {
|
|
123
124
|
const fileBuffer = readFileSync(urlObject);
|
|
124
|
-
const content =
|
|
125
|
+
const content = CONTENT_TYPE.isTextual(contentType)
|
|
126
|
+
? String(fileBuffer)
|
|
127
|
+
: fileBuffer;
|
|
125
128
|
return {
|
|
126
129
|
content,
|
|
127
130
|
contentType,
|
|
@@ -138,7 +141,7 @@ export const jsenvPluginProtocolFile = ({
|
|
|
138
141
|
const parentDirectoryContentArray = readdirSync(
|
|
139
142
|
new URL(parentDirectoryUrl),
|
|
140
143
|
);
|
|
141
|
-
const html =
|
|
144
|
+
const html = generateHtmlForENOENT(
|
|
142
145
|
urlInfo.url,
|
|
143
146
|
parentDirectoryContentArray,
|
|
144
147
|
parentDirectoryUrl,
|
|
@@ -146,6 +149,7 @@ export const jsenvPluginProtocolFile = ({
|
|
|
146
149
|
directoryListingUrlMocks,
|
|
147
150
|
);
|
|
148
151
|
return {
|
|
152
|
+
status: 404,
|
|
149
153
|
contentType: "text/html",
|
|
150
154
|
content: html,
|
|
151
155
|
headers: {
|
|
@@ -191,7 +195,7 @@ const generateHtmlForDirectory = (
|
|
|
191
195
|
const html = replacePlaceholders(htmlForDirectory, replacers);
|
|
192
196
|
return html;
|
|
193
197
|
};
|
|
194
|
-
const
|
|
198
|
+
const generateHtmlForENOENT = (
|
|
195
199
|
url,
|
|
196
200
|
parentDirectoryContentArray,
|
|
197
201
|
parentDirectoryUrl,
|