@jsenv/core 41.2.7 → 41.2.8

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.
@@ -6411,7 +6411,30 @@ const jsenvPluginDirectoryListing = ({
6411
6411
  const { request, requestedUrl, mainFilePath, rootDirectoryUrl } =
6412
6412
  reference.ownerUrlInfo.context;
6413
6413
  if (!fsStat) {
6414
- if (!request || request.headers["sec-fetch-dest"] !== "document") {
6414
+ if (!request) {
6415
+ // no request we should not serve directoy listing
6416
+ return null;
6417
+ }
6418
+ const secFetchDest = request.headers["sec-fetch-dest"];
6419
+ if (secFetchDest && secFetchDest !== "document") {
6420
+ // we have sec fetch dest and it's not document so it's not a navigation request, we should not serve directory listing
6421
+ return null;
6422
+ }
6423
+ if (!secFetchDest) {
6424
+ // beware we might end up here when nav context is not trusted (http, ip url etc)
6425
+ // in that case we fallback to detecting if the request explicitly accepts html.
6426
+ // browsers navigating to a page send "text/html,..." explicitly; programmatic
6427
+ // fetch clients like Node.js send "*/*" which should NOT trigger directory listing.
6428
+ // We must NOT use pickContentType here because it matches "text/html" via the
6429
+ // "*/*" wildcard, causing programmatic fetches to receive the directory listing
6430
+ // HTML page (status 200) instead of a 404.
6431
+ const acceptHeader = request.headers.accept || "";
6432
+ if (!acceptHeader.includes("text/html")) {
6433
+ return null;
6434
+ }
6435
+ }
6436
+ // requestedUrl must be a proper file:// URL (no encoded slashes)
6437
+ if (requestedUrl.includes("%2F") || requestedUrl.includes("%2f")) {
6415
6438
  return null;
6416
6439
  }
6417
6440
  if (url !== requestedUrl) {
@@ -5742,13 +5742,11 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
5742
5742
  if (packageSpecifier === "") {
5743
5743
  throw new Error("invalid module specifier");
5744
5744
  }
5745
- if (
5746
- conditions.includes("node") &&
5747
- isSpecifierForNodeBuiltin(packageSpecifier)
5748
- ) {
5745
+ // "node:" prefixed specifiers always resolve to node builtins
5746
+ if (packageSpecifier.startsWith("node:")) {
5749
5747
  return createResolutionResult({
5750
5748
  type: "node_builtin_specifier",
5751
- url: `node:${packageSpecifier}`,
5749
+ url: packageSpecifier,
5752
5750
  });
5753
5751
  }
5754
5752
  let { packageName, packageSubpath } = parsePackageSpecifier(packageSpecifier);
@@ -5808,6 +5806,17 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
5808
5806
  packageJson,
5809
5807
  });
5810
5808
  }
5809
+ // Bare builtin names (without "node:" prefix) are valid only if no local package found
5810
+ // Local packages always take priority over builtins with the same name
5811
+ if (
5812
+ conditions.includes("node") &&
5813
+ isSpecifierForNodeBuiltin(packageSpecifier)
5814
+ ) {
5815
+ return createResolutionResult({
5816
+ type: "node_builtin_specifier",
5817
+ url: `node:${packageSpecifier}`,
5818
+ });
5819
+ }
5811
5820
  throw createModuleNotFoundError(packageName, resolutionContext);
5812
5821
  };
5813
5822
 
@@ -5,6 +5,7 @@
5
5
  <meta charset="utf-8">
6
6
  <link rel="icon" href="data:,">
7
7
  <link rel="stylesheet" href="./css/directory_listing.css">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
9
  </head>
9
10
 
10
11
  <body data-theme="dark">
@@ -5208,13 +5208,11 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
5208
5208
  if (packageSpecifier === "") {
5209
5209
  throw new Error("invalid module specifier");
5210
5210
  }
5211
- if (
5212
- conditions.includes("node") &&
5213
- isSpecifierForNodeBuiltin(packageSpecifier)
5214
- ) {
5211
+ // "node:" prefixed specifiers always resolve to node builtins
5212
+ if (packageSpecifier.startsWith("node:")) {
5215
5213
  return createResolutionResult({
5216
5214
  type: "node_builtin_specifier",
5217
- url: `node:${packageSpecifier}`,
5215
+ url: packageSpecifier,
5218
5216
  });
5219
5217
  }
5220
5218
  let { packageName, packageSubpath } = parsePackageSpecifier(packageSpecifier);
@@ -5274,6 +5272,17 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
5274
5272
  packageJson,
5275
5273
  });
5276
5274
  }
5275
+ // Bare builtin names (without "node:" prefix) are valid only if no local package found
5276
+ // Local packages always take priority over builtins with the same name
5277
+ if (
5278
+ conditions.includes("node") &&
5279
+ isSpecifierForNodeBuiltin(packageSpecifier)
5280
+ ) {
5281
+ return createResolutionResult({
5282
+ type: "node_builtin_specifier",
5283
+ url: `node:${packageSpecifier}`,
5284
+ });
5285
+ }
5277
5286
  throw createModuleNotFoundError(packageName, resolutionContext);
5278
5287
  };
5279
5288
 
@@ -2471,7 +2471,30 @@ const jsenvPluginDirectoryListing = ({
2471
2471
  const { request, requestedUrl, mainFilePath, rootDirectoryUrl } =
2472
2472
  reference.ownerUrlInfo.context;
2473
2473
  if (!fsStat) {
2474
- if (!request || request.headers["sec-fetch-dest"] !== "document") {
2474
+ if (!request) {
2475
+ // no request we should not serve directoy listing
2476
+ return null;
2477
+ }
2478
+ const secFetchDest = request.headers["sec-fetch-dest"];
2479
+ if (secFetchDest && secFetchDest !== "document") {
2480
+ // we have sec fetch dest and it's not document so it's not a navigation request, we should not serve directory listing
2481
+ return null;
2482
+ }
2483
+ if (!secFetchDest) {
2484
+ // beware we might end up here when nav context is not trusted (http, ip url etc)
2485
+ // in that case we fallback to detecting if the request explicitly accepts html.
2486
+ // browsers navigating to a page send "text/html,..." explicitly; programmatic
2487
+ // fetch clients like Node.js send "*/*" which should NOT trigger directory listing.
2488
+ // We must NOT use pickContentType here because it matches "text/html" via the
2489
+ // "*/*" wildcard, causing programmatic fetches to receive the directory listing
2490
+ // HTML page (status 200) instead of a 404.
2491
+ const acceptHeader = request.headers.accept || "";
2492
+ if (!acceptHeader.includes("text/html")) {
2493
+ return null;
2494
+ }
2495
+ }
2496
+ // requestedUrl must be a proper file:// URL (no encoded slashes)
2497
+ if (requestedUrl.includes("%2F") || requestedUrl.includes("%2f")) {
2475
2498
  return null;
2476
2499
  }
2477
2500
  if (url !== requestedUrl) {
@@ -10148,7 +10171,7 @@ const startDevServer = async ({
10148
10171
  ignore,
10149
10172
  port = 3456,
10150
10173
  hostname,
10151
- acceptAnyIp,
10174
+ acceptAnyIp = true,
10152
10175
  https,
10153
10176
  // it's better to use http1 by default because it allows to get statusText in devtools
10154
10177
  // which gives valuable information when there is errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "41.2.7",
3
+ "version": "41.2.8",
4
4
  "type": "module",
5
5
  "description": "Tool to develop, test and build js projects",
6
6
  "repository": {
@@ -72,14 +72,14 @@
72
72
  "test:snapshot_clear": "npx @jsenv/filesystem clear **/tests/**/side_effects/"
73
73
  },
74
74
  "dependencies": {
75
- "@jsenv/ast": "6.8.1",
76
- "@jsenv/js-module-fallback": "1.4.31",
77
- "@jsenv/plugin-bundling": "2.10.11",
75
+ "@jsenv/ast": "6.8.2",
76
+ "@jsenv/js-module-fallback": "1.4.32",
77
+ "@jsenv/plugin-bundling": "2.10.12",
78
78
  "@jsenv/plugin-minification": "1.7.3",
79
- "@jsenv/plugin-supervisor": "1.8.2",
80
- "@jsenv/plugin-transpilation": "1.5.73",
79
+ "@jsenv/plugin-supervisor": "1.8.3",
80
+ "@jsenv/plugin-transpilation": "1.5.74",
81
81
  "@jsenv/server": "17.3.0",
82
- "@jsenv/sourcemap": "1.3.17",
82
+ "@jsenv/sourcemap": "1.3.18",
83
83
  "react-table": "7.8.0"
84
84
  },
85
85
  "devDependencies": {
@@ -53,7 +53,7 @@ export const startDevServer = async ({
53
53
  ignore,
54
54
  port = 3456,
55
55
  hostname,
56
- acceptAnyIp,
56
+ acceptAnyIp = true,
57
57
  https,
58
58
  // it's better to use http1 by default because it allows to get statusText in devtools
59
59
  // which gives valuable information when there is errors
@@ -5,6 +5,7 @@
5
5
  <meta charset="utf-8" />
6
6
  <link rel="icon" href="data:," />
7
7
  <link rel="stylesheet" href="./directory_listing.css" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
9
  </head>
9
10
 
10
11
  <body data-theme="dark">
@@ -71,7 +71,30 @@ export const jsenvPluginDirectoryListing = ({
71
71
  const { request, requestedUrl, mainFilePath, rootDirectoryUrl } =
72
72
  reference.ownerUrlInfo.context;
73
73
  if (!fsStat) {
74
- if (!request || request.headers["sec-fetch-dest"] !== "document") {
74
+ if (!request) {
75
+ // no request we should not serve directoy listing
76
+ return null;
77
+ }
78
+ const secFetchDest = request.headers["sec-fetch-dest"];
79
+ if (secFetchDest && secFetchDest !== "document") {
80
+ // we have sec fetch dest and it's not document so it's not a navigation request, we should not serve directory listing
81
+ return null;
82
+ }
83
+ if (!secFetchDest) {
84
+ // beware we might end up here when nav context is not trusted (http, ip url etc)
85
+ // in that case we fallback to detecting if the request explicitly accepts html.
86
+ // browsers navigating to a page send "text/html,..." explicitly; programmatic
87
+ // fetch clients like Node.js send "*/*" which should NOT trigger directory listing.
88
+ // We must NOT use pickContentType here because it matches "text/html" via the
89
+ // "*/*" wildcard, causing programmatic fetches to receive the directory listing
90
+ // HTML page (status 200) instead of a 404.
91
+ const acceptHeader = request.headers.accept || "";
92
+ if (!acceptHeader.includes("text/html")) {
93
+ return null;
94
+ }
95
+ }
96
+ // requestedUrl must be a proper file:// URL (no encoded slashes)
97
+ if (requestedUrl.includes("%2F") || requestedUrl.includes("%2f")) {
75
98
  return null;
76
99
  }
77
100
  if (url !== requestedUrl) {