@jsenv/core 36.0.2 → 36.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "36.0.2",
3
+ "version": "36.1.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -69,13 +69,13 @@
69
69
  "@jsenv/integrity": "0.0.1",
70
70
  "@jsenv/log": "3.3.5",
71
71
  "@jsenv/node-esm-resolution": "1.0.1",
72
+ "@jsenv/plugin-supervisor": "1.0.0",
72
73
  "@jsenv/server": "15.0.3",
73
74
  "@jsenv/sourcemap": "1.0.10",
74
75
  "@jsenv/url-meta": "8.1.0",
75
76
  "@jsenv/urls": "2.0.0",
76
77
  "@jsenv/utils": "2.0.1",
77
78
  "construct-style-sheets-polyfill": "3.1.0",
78
- "launch-editor": "2.6.0",
79
79
  "lightningcss": "1.20.0"
80
80
  },
81
81
  "devDependencies": {
@@ -92,11 +92,11 @@
92
92
  "@jsenv/plugin-placeholders": "./packages/jsenv-plugin-placeholders/",
93
93
  "@jsenv/plugin-as-js-classic": "./packages/jsenv-plugin-as-js-classic/",
94
94
  "@jsenv/test": "./packages/test/",
95
- "eslint": "8.40.0",
95
+ "eslint": "8.41.0",
96
96
  "eslint-plugin-html": "7.1.0",
97
97
  "eslint-plugin-import": "2.27.5",
98
98
  "eslint-plugin-react": "7.32.2",
99
- "playwright": "1.33.0",
99
+ "playwright": "1.34.2",
100
100
  "prettier": "2.8.8"
101
101
  }
102
102
  }
@@ -130,6 +130,7 @@ export const build = async ({
130
130
  buildDirectoryUrl,
131
131
  entryPoints = {},
132
132
  assetsDirectory = "",
133
+ ignore,
133
134
 
134
135
  runtimeCompat = defaultRuntimeCompat,
135
136
  base = runtimeCompat.node ? "./" : "/",
@@ -311,6 +312,10 @@ build ${entryPointKeys.length} entry points`);
311
312
  signal,
312
313
  logLevel,
313
314
  rootDirectoryUrl: sourceDirectoryUrl,
315
+ ignore,
316
+ // during first pass (craft) we keep "ignore:" when a reference is ignored
317
+ // so that the second pass (shape) properly ignore those urls
318
+ ignoreProtocol: "keep",
314
319
  urlGraph: rawGraph,
315
320
  build: true,
316
321
  runtimeCompat,
@@ -332,13 +337,7 @@ build ${entryPointKeys.length} entry points`);
332
337
  rootDirectoryUrl: sourceDirectoryUrl,
333
338
  urlGraph: rawGraph,
334
339
  runtimeCompat,
335
-
336
- referenceAnalysis: {
337
- ...referenceAnalysis,
338
- // during first pass (craft) we inject "ignore:" when a reference must be ignored
339
- // so that the second pass (shape) properly ignore those urls
340
- ignoreProtocol: "inject",
341
- },
340
+ referenceAnalysis,
342
341
  nodeEsmResolution,
343
342
  magicExtensions,
344
343
  magicDirectoryIndex,
@@ -383,6 +382,14 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
383
382
  const finalGraphKitchen = createKitchen({
384
383
  logLevel,
385
384
  rootDirectoryUrl: buildDirectoryUrl,
385
+ // here most plugins are not there
386
+ // - no external plugin
387
+ // - no plugin putting reference.mustIgnore on https urls
388
+ // At this stage it's only about redirecting urls to the build directory
389
+ // consequently only a subset or urls are supported
390
+ supportedProtocols: ["file:", "data:", "virtual:", "ignore:"],
391
+ ignore,
392
+ ignoreProtocol: versioning ? "keep" : "remove",
386
393
  urlGraph: finalGraph,
387
394
  build: true,
388
395
  runtimeCompat,
@@ -390,14 +397,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
390
397
  plugins: [
391
398
  jsenvPluginReferenceAnalysis({
392
399
  ...referenceAnalysis,
393
- // here most plugins are not there
394
- // - no external plugin
395
- // - no plugin putting reference.mustIgnore on https urls
396
- // At this stage it's only about redirecting urls to the build directory
397
- // consequently only a subset or urls are supported
398
- supportedProtocols: ["file:", "data:", "virtual:", "ignore:"],
399
400
  fetchInlineUrls: false,
400
- ignoreProtocol: versioning ? "keep" : "remove",
401
401
  }),
402
402
  ...(lineBreakNormalization
403
403
  ? [jsenvPluginLineBreakNormalization()]
@@ -1063,14 +1063,11 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1063
1063
  const contentVersionMap = new Map();
1064
1064
  const hashCallbacks = [];
1065
1065
  GRAPH.forEach(finalGraph, (urlInfo) => {
1066
- if (urlInfo.url.startsWith("data:")) {
1067
- return;
1068
- }
1069
1066
  if (urlInfo.type === "sourcemap") {
1070
1067
  return;
1071
1068
  }
1072
1069
  // ignore:
1073
- // - inline files:
1070
+ // - inline files and data files:
1074
1071
  // they are already taken into account in the file where they appear
1075
1072
  // - ignored files:
1076
1073
  // we don't know their content
@@ -1082,7 +1079,10 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1082
1079
  if (urlInfo.isInline) {
1083
1080
  return;
1084
1081
  }
1085
- if (urlInfo.mustIgnore) {
1082
+ if (urlInfo.url.startsWith("data:")) {
1083
+ return;
1084
+ }
1085
+ if (urlInfo.url.startsWith("ignore:")) {
1086
1086
  return;
1087
1087
  }
1088
1088
  if (urlInfo.dependents.size === 0 && !urlInfo.isEntryPoint) {
@@ -1116,7 +1116,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1116
1116
  );
1117
1117
  if (!dependencyContentVersion) {
1118
1118
  // no content generated for this dependency
1119
- // (inline, data:, sourcemap, mustIgnore is true, ...)
1119
+ // (inline, data:, ignore:, sourcemap, ...)
1120
1120
  return null;
1121
1121
  }
1122
1122
  if (preferWithoutVersioning(reference)) {
@@ -1182,20 +1182,15 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1182
1182
  const versioningKitchen = createKitchen({
1183
1183
  logLevel: logger.level,
1184
1184
  rootDirectoryUrl: buildDirectoryUrl,
1185
+ ignore,
1186
+ ignoreProtocol: "remove",
1185
1187
  urlGraph: finalGraph,
1186
1188
  build: true,
1187
1189
  runtimeCompat,
1188
1190
  ...contextSharedDuringBuild,
1189
1191
  plugins: [
1190
- // here most plugins are not there
1191
- // - no external plugin
1192
- // - no plugin putting reference.mustIgnore on https urls
1193
- // At this stage it's only about versioning urls
1194
- // consequently only a subset or urls are supported
1195
1192
  jsenvPluginReferenceAnalysis({
1196
1193
  ...referenceAnalysis,
1197
- supportedProtocols: ["file:", "data:", "virtual:"],
1198
- ignoreProtocol: "remove",
1199
1194
  fetchInlineUrls: false,
1200
1195
  inlineConvertedScript: true, // to be able to version their urls
1201
1196
  allowEscapeForVersioning: true,
@@ -1238,10 +1233,13 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1238
1233
  return url;
1239
1234
  },
1240
1235
  formatReference: (reference) => {
1241
- if (reference.mustIgnore) {
1236
+ if (reference.url.startsWith("ignore:")) {
1237
+ return null;
1238
+ }
1239
+ if (reference.isInline) {
1242
1240
  return null;
1243
1241
  }
1244
- if (reference.isInline || reference.url.startsWith("data:")) {
1242
+ if (reference.url.startsWith("data:")) {
1245
1243
  return null;
1246
1244
  }
1247
1245
  if (reference.isResourceHint) {
@@ -1255,9 +1253,6 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1255
1253
  if (!canUseVersionedUrl(referencedUrlInfo)) {
1256
1254
  return reference.specifier;
1257
1255
  }
1258
- if (referencedUrlInfo.mustIgnore) {
1259
- return null;
1260
- }
1261
1256
  const versionedUrl = versionedUrlMap.get(reference.url);
1262
1257
  if (!versionedUrl) {
1263
1258
  // happens for sourcemap
@@ -1384,9 +1379,6 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1384
1379
  }
1385
1380
  cleanup_jsenv_attributes_from_html: {
1386
1381
  GRAPH.forEach(finalGraph, (urlInfo) => {
1387
- if (urlInfo.mustIgnore) {
1388
- return;
1389
- }
1390
1382
  if (!urlInfo.url.startsWith("file:")) {
1391
1383
  return;
1392
1384
  }
@@ -1569,10 +1561,10 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1569
1561
  if (serviceWorkerEntryUrlInfos.length > 0) {
1570
1562
  const serviceWorkerResources = {};
1571
1563
  GRAPH.forEach(finalGraph, (urlInfo) => {
1572
- if (urlInfo.isInline || urlInfo.mustIgnore) {
1564
+ if (!urlInfo.url.startsWith("file:")) {
1573
1565
  return;
1574
1566
  }
1575
- if (!urlInfo.url.startsWith("file:")) {
1567
+ if (urlInfo.isInline) {
1576
1568
  return;
1577
1569
  }
1578
1570
  if (!canUseVersionedUrl(urlInfo)) {
@@ -1642,9 +1634,6 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1642
1634
  return buildRelativeUrl;
1643
1635
  };
1644
1636
  GRAPH.forEach(finalGraph, (urlInfo) => {
1645
- if (urlInfo.mustIgnore) {
1646
- return;
1647
- }
1648
1637
  if (!urlInfo.url.startsWith("file:")) {
1649
1638
  return;
1650
1639
  }
@@ -22,6 +22,7 @@ export const createFileService = ({
22
22
 
23
23
  sourceDirectoryUrl,
24
24
  sourceMainFilePath,
25
+ ignore,
25
26
  sourceFilesConfig,
26
27
  runtimeCompat,
27
28
 
@@ -97,6 +98,7 @@ export const createFileService = ({
97
98
  logLevel,
98
99
  rootDirectoryUrl: sourceDirectoryUrl,
99
100
  mainFilePath: sourceMainFilePath,
101
+ ignore,
100
102
  urlGraph,
101
103
  dev: true,
102
104
  runtimeCompat,
@@ -252,7 +254,11 @@ export const createFileService = ({
252
254
  return responseFromPlugin;
253
255
  }
254
256
  let reference;
255
- const parentUrl = inferParentFromRequest(request, sourceDirectoryUrl);
257
+ const parentUrl = inferParentFromRequest(
258
+ request,
259
+ sourceDirectoryUrl,
260
+ sourceMainFilePath,
261
+ );
256
262
  if (parentUrl) {
257
263
  reference = urlGraph.inferReference(request.resource, parentUrl);
258
264
  }
@@ -423,7 +429,11 @@ export const createFileService = ({
423
429
  };
424
430
  };
425
431
 
426
- const inferParentFromRequest = (request, sourceDirectoryUrl) => {
432
+ const inferParentFromRequest = (
433
+ request,
434
+ sourceDirectoryUrl,
435
+ sourceMainFilePath,
436
+ ) => {
427
437
  const { referer } = request.headers;
428
438
  if (!referer) {
429
439
  return null;
@@ -431,7 +441,12 @@ const inferParentFromRequest = (request, sourceDirectoryUrl) => {
431
441
  const refererUrlObject = new URL(referer);
432
442
  refererUrlObject.searchParams.delete("hmr");
433
443
  refererUrlObject.searchParams.delete("v");
434
- return WEB_URL_CONVERTER.asFileUrl(referer, {
444
+
445
+ let refererUrl = refererUrlObject.href;
446
+ if (refererUrl === `${request.origin}/`) {
447
+ refererUrl = new URL(sourceMainFilePath, request.origin).href;
448
+ }
449
+ return WEB_URL_CONVERTER.asFileUrl(refererUrl, {
435
450
  origin: request.origin,
436
451
  rootDirectoryUrl: sourceDirectoryUrl,
437
452
  });
@@ -25,6 +25,7 @@ import { createFileService } from "./file_service.js";
25
25
  export const startDevServer = async ({
26
26
  sourceDirectoryUrl,
27
27
  sourceMainFilePath = "./index.html",
28
+ ignore,
28
29
  port = 3456,
29
30
  hostname,
30
31
  acceptAnyIp,
@@ -186,6 +187,7 @@ export const startDevServer = async ({
186
187
 
187
188
  sourceDirectoryUrl,
188
189
  sourceMainFilePath,
190
+ ignore,
189
191
  sourceFilesConfig,
190
192
  runtimeCompat,
191
193
 
@@ -6,6 +6,7 @@ import {
6
6
  normalizeUrl,
7
7
  setUrlFilename,
8
8
  } from "@jsenv/urls";
9
+ import { URL_META } from "@jsenv/url-meta";
9
10
  import { writeFileSync, ensureWindowsDriveLetter } from "@jsenv/filesystem";
10
11
  import { createLogger, createDetailedMessage, ANSI } from "@jsenv/log";
11
12
  import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
@@ -29,6 +30,9 @@ export const createKitchen = ({
29
30
 
30
31
  rootDirectoryUrl,
31
32
  mainFilePath,
33
+ ignore,
34
+ ignoreProtocol = "remove",
35
+ supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
32
36
  urlGraph,
33
37
  dev = false,
34
38
  build = false,
@@ -72,6 +76,35 @@ export const createKitchen = ({
72
76
  pluginController.pushPlugin(pluginEntry);
73
77
  });
74
78
 
79
+ const isIgnoredByProtocol = (url) => {
80
+ const { protocol } = new URL(url);
81
+ const protocolIsSupported = supportedProtocols.some(
82
+ (supportedProtocol) => protocol === supportedProtocol,
83
+ );
84
+ return !protocolIsSupported;
85
+ };
86
+ let isIgnoredByParam = () => false;
87
+ if (ignore) {
88
+ const associations = URL_META.resolveAssociations(
89
+ { ignore },
90
+ rootDirectoryUrl,
91
+ );
92
+ const cache = new Map();
93
+ isIgnoredByParam = (url) => {
94
+ const fromCache = cache.get(url);
95
+ if (fromCache) return fromCache;
96
+ const { ignore } = URL_META.applyAssociations({
97
+ url,
98
+ associations,
99
+ });
100
+ cache.set(url, ignore);
101
+ return ignore;
102
+ };
103
+ }
104
+ const isIgnored = (url) => {
105
+ return isIgnoredByProtocol(url) || isIgnoredByParam(url);
106
+ };
107
+
75
108
  /*
76
109
  * - "http_request"
77
110
  * - "entry_point"
@@ -116,7 +149,6 @@ export const createKitchen = ({
116
149
  specifierColumn,
117
150
  baseUrl,
118
151
  isOriginalPosition,
119
- mustIgnore,
120
152
  isEntryPoint = false,
121
153
  isResourceHint = false,
122
154
  isImplicit = false,
@@ -165,7 +197,6 @@ export const createKitchen = ({
165
197
  specifierColumn,
166
198
  isOriginalPosition,
167
199
  baseUrl,
168
- mustIgnore,
169
200
  isEntryPoint,
170
201
  isResourceHint,
171
202
  isImplicit,
@@ -216,13 +247,36 @@ export const createKitchen = ({
216
247
  url = normalizeUrl(url);
217
248
  let referencedUrlObject;
218
249
  let searchParams;
219
- const onReferenceUrlChange = (referenceUrl) => {
250
+ const setReferenceUrl = (referenceUrl) => {
251
+ // ignored urls are prefixed with "ignore:" so that reference are associated
252
+ // to a dedicated urlInfo that is ignored.
253
+ // this way it's only once a resource is referenced by reference that is not ignored
254
+ // that the resource is cooked
255
+ if (
256
+ reference.specifier[0] === "#" &&
257
+ // For Html, css and "#" refer to a resource in the page, reference must be preserved
258
+ // However for js import specifiers they have a different meaning and we want
259
+ // to resolve them (https://nodejs.org/api/packages.html#imports for instance)
260
+ reference.type !== "js_import"
261
+ ) {
262
+ referenceUrl = `ignore:${referenceUrl}`;
263
+ } else if (isIgnored(referenceUrl)) {
264
+ referenceUrl = `ignore:${referenceUrl}`;
265
+ }
266
+
267
+ if (
268
+ referenceUrl.startsWith("ignore:") &&
269
+ !reference.specifier.startsWith("ignore:")
270
+ ) {
271
+ reference.specifier = `ignore:${reference.specifier}`;
272
+ }
273
+
220
274
  referencedUrlObject = new URL(referenceUrl);
221
275
  searchParams = referencedUrlObject.searchParams;
222
276
  reference.url = referenceUrl;
223
277
  reference.searchParams = searchParams;
224
278
  };
225
- onReferenceUrlChange(url);
279
+ setReferenceUrl(url);
226
280
 
227
281
  if (reference.debug) {
228
282
  logger.debug(`url resolved by "${
@@ -251,7 +305,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
251
305
  }
252
306
  const prevReference = { ...reference };
253
307
  updateReference(prevReference, reference);
254
- onReferenceUrlChange(normalizedReturnValue);
308
+ setReferenceUrl(normalizedReturnValue);
255
309
  },
256
310
  );
257
311
  reference.generatedUrl = reference.url;
@@ -276,12 +330,16 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
276
330
  reference.generatedUrl = normalizeUrl(referencedUrlObject.href);
277
331
  },
278
332
  );
333
+
279
334
  const returnValue = pluginController.callHooksUntil(
280
335
  "formatReference",
281
336
  reference,
282
337
  referenceContext,
283
338
  );
284
- if (reference.mustIgnore) {
339
+ if (reference.url.startsWith("ignore:")) {
340
+ if (ignoreProtocol === "remove") {
341
+ reference.specifier = reference.specifier.slice("ignore:".length);
342
+ }
285
343
  reference.generatedSpecifier = reference.specifier;
286
344
  reference.generatedSpecifier = urlSpecifierEncoding.encode(reference);
287
345
  } else {
@@ -469,7 +527,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
469
527
  });
470
528
  };
471
529
 
472
- if (!urlInfo.mustIgnore) {
530
+ if (!urlInfo.url.startsWith("ignore:")) {
473
531
  // references
474
532
  const references = [];
475
533
  context.referenceUtils = {
@@ -854,11 +912,6 @@ const traceFromUrlSite = (urlSite) => {
854
912
  };
855
913
 
856
914
  const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
857
- if (reference.mustIgnore) {
858
- urlInfo.mustIgnore = true;
859
- } else {
860
- urlInfo.mustIgnore = false;
861
- }
862
915
  urlInfo.originalUrl = urlInfo.originalUrl || reference.url;
863
916
 
864
917
  if (reference.isEntryPoint || isWebWorkerEntryPointReference(reference)) {
@@ -30,15 +30,19 @@ const createUrlGraphReport = (urlGraph) => {
30
30
  total: 0,
31
31
  };
32
32
  urlGraph.urlInfoMap.forEach((urlInfo) => {
33
- if (urlInfo.url.startsWith("data:")) {
34
- return;
35
- }
36
33
  // ignore:
37
- // - inline files: they are already taken into account in the file where they appear
38
34
  // - ignored files: we don't know their content
39
- if (urlInfo.isInline || urlInfo.mustIgnore) {
35
+ // - inline files and data files: they are already taken into account in the file where they appear
36
+ if (urlInfo.url.startsWith("ignore:")) {
37
+ return;
38
+ }
39
+ if (urlInfo.isInline) {
40
40
  return;
41
41
  }
42
+ if (urlInfo.url.startsWith("data:")) {
43
+ return;
44
+ }
45
+
42
46
  // file loaded via import assertion are already inside the graph
43
47
  // their js module equivalent are ignored to avoid counting it twice
44
48
  // in the build graph the file targeted by import assertion will likely be gone
@@ -268,7 +268,6 @@ const createUrlInfo = (url) => {
268
268
  originalUrl: undefined,
269
269
  filename: "",
270
270
  isEntryPoint: false,
271
- mustIgnore: undefined,
272
271
  originalContent: undefined,
273
272
  content: undefined,
274
273
 
@@ -153,7 +153,11 @@ export const createPluginController = (kitchenContext) => {
153
153
  info.timing[`${hook.name}-${hook.plugin.name.replace("jsenv:", "")}`] =
154
154
  performance.now() - startTimestamp;
155
155
  }
156
- valueReturned = assertAndNormalizeReturnValue(hook.name, valueReturned);
156
+ valueReturned = assertAndNormalizeReturnValue(
157
+ hook.name,
158
+ valueReturned,
159
+ info,
160
+ );
157
161
  return valueReturned;
158
162
  };
159
163
  const callAsyncHook = async (hook, info, context) => {
@@ -176,7 +180,11 @@ export const createPluginController = (kitchenContext) => {
176
180
  info.timing[`${hook.name}-${hook.plugin.name.replace("jsenv:", "")}`] =
177
181
  performance.now() - startTimestamp;
178
182
  }
179
- valueReturned = assertAndNormalizeReturnValue(hook.name, valueReturned);
183
+ valueReturned = assertAndNormalizeReturnValue(
184
+ hook.name,
185
+ valueReturned,
186
+ info,
187
+ );
180
188
  return valueReturned;
181
189
  };
182
190
 
@@ -277,7 +285,7 @@ const getHookFunction = (
277
285
  return hookValue;
278
286
  };
279
287
 
280
- const assertAndNormalizeReturnValue = (hookName, returnValue) => {
288
+ const assertAndNormalizeReturnValue = (hookName, returnValue, info) => {
281
289
  // all hooks are allowed to return null/undefined as a signal of "I don't do anything"
282
290
  if (returnValue === null || returnValue === undefined) {
283
291
  return returnValue;
@@ -286,7 +294,7 @@ const assertAndNormalizeReturnValue = (hookName, returnValue) => {
286
294
  if (!returnValueAssertion.appliesTo.includes(hookName)) {
287
295
  continue;
288
296
  }
289
- const assertionResult = returnValueAssertion.assertion(returnValue);
297
+ const assertionResult = returnValueAssertion.assertion(returnValue, info);
290
298
  if (assertionResult !== undefined) {
291
299
  // normalization
292
300
  returnValue = assertionResult;
@@ -320,13 +328,13 @@ const returnValueAssertions = [
320
328
  "finalizeUrlContent",
321
329
  "optimizeUrlContent",
322
330
  ],
323
- assertion: (valueReturned) => {
331
+ assertion: (valueReturned, urlInfo) => {
324
332
  if (typeof valueReturned === "string" || Buffer.isBuffer(valueReturned)) {
325
333
  return { content: valueReturned };
326
334
  }
327
335
  if (typeof valueReturned === "object") {
328
- const { mustIgnore, content, body } = valueReturned;
329
- if (mustIgnore) {
336
+ const { content, body } = valueReturned;
337
+ if (urlInfo.url.startsWith("ignore:")) {
330
338
  return undefined;
331
339
  }
332
340
  if (typeof content !== "string" && !Buffer.isBuffer(content) && !body) {
@@ -1,3 +1,5 @@
1
+ import { jsenvPluginSupervisor } from "@jsenv/plugin-supervisor";
2
+
1
3
  import { jsenvPluginReferenceAnalysis } from "./reference_analysis/jsenv_plugin_reference_analysis.js";
2
4
  import { jsenvPluginImportmap } from "./importmap/jsenv_plugin_importmap.js";
3
5
  import { jsenvPluginNodeEsmResolution } from "./resolution_node_esm/jsenv_plugin_node_esm_resolution.js";
@@ -6,7 +8,6 @@ import { jsenvPluginVersionSearchParam } from "./version_search_param/jsenv_plug
6
8
  import { jsenvPluginProtocolFile } from "./protocol_file/jsenv_plugin_protocol_file.js";
7
9
  import { jsenvPluginProtocolHttp } from "./protocol_http/jsenv_plugin_protocol_http.js";
8
10
  import { jsenvPluginInlining } from "./inlining/jsenv_plugin_inlining.js";
9
- import { jsenvPluginSupervisor } from "./supervisor/jsenv_plugin_supervisor.js";
10
11
  import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_commonjs_globals.js";
11
12
  import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js";
12
13
  import { jsenvPluginGlobalScenarios } from "./global_scenarios/jsenv_plugin_global_scenarios.js";
@@ -30,6 +30,23 @@ export const jsenvPluginProtocolFile = ({
30
30
  if (reference.isInline) {
31
31
  return null;
32
32
  }
33
+ // ignore root file url
34
+ if (reference.url === "file:///" || reference.url === "file://") {
35
+ reference.leadsToADirectory = true;
36
+ return `ignore:file:///`;
37
+ }
38
+ // ignore "./" on new URL("./")
39
+ if (
40
+ reference.subtype === "new_url_first_arg" &&
41
+ reference.specifier === "./"
42
+ ) {
43
+ return `ignore:${reference.url}`;
44
+ }
45
+ // ignore all new URL second arg
46
+ if (reference.subtype === "new_url_second_arg") {
47
+ return `ignore:${reference.url}`;
48
+ }
49
+
33
50
  const urlObject = new URL(reference.url);
34
51
  let stat;
35
52
  try {
@@ -41,11 +58,13 @@ export const jsenvPluginProtocolFile = ({
41
58
  throw e;
42
59
  }
43
60
  }
61
+
44
62
  const { search, hash } = urlObject;
45
63
  let { pathname } = urlObject;
46
64
  const pathnameUsesTrailingSlash = pathname.endsWith("/");
47
65
  urlObject.search = "";
48
66
  urlObject.hash = "";
67
+
49
68
  // force trailing slash on directories
50
69
  if (stat && stat.isDirectory() && !pathnameUsesTrailingSlash) {
51
70
  urlObject.pathname = `${pathname}/`;
@@ -57,46 +76,32 @@ export const jsenvPluginProtocolFile = ({
57
76
  }
58
77
 
59
78
  let url = urlObject.href;
60
- const mustIgnore =
61
- stat &&
62
- stat.isDirectory() &&
63
- // ignore new URL second arg
64
- (reference.subtype === "new_url_second_arg" ||
65
- // ignore root file url
66
- reference.url === "file:///" ||
67
- (reference.subtype === "new_url_first_arg" &&
68
- reference.specifier === "./"));
69
-
70
- if (mustIgnore) {
71
- reference.mustIgnore = true;
72
- } else {
73
- const shouldApplyDilesystemMagicResolution =
74
- reference.type === "js_import";
75
- if (shouldApplyDilesystemMagicResolution) {
76
- const filesystemResolution = applyFileSystemMagicResolution(url, {
77
- fileStat: stat,
78
- magicDirectoryIndex,
79
- magicExtensions: getExtensionsToTry(
80
- magicExtensions,
81
- reference.parentUrl,
82
- ),
83
- });
84
- if (filesystemResolution.stat) {
85
- stat = filesystemResolution.stat;
86
- url = filesystemResolution.url;
87
- }
79
+ const shouldApplyDilesystemMagicResolution =
80
+ reference.type === "js_import";
81
+ if (shouldApplyDilesystemMagicResolution) {
82
+ const filesystemResolution = applyFileSystemMagicResolution(url, {
83
+ fileStat: stat,
84
+ magicDirectoryIndex,
85
+ magicExtensions: getExtensionsToTry(
86
+ magicExtensions,
87
+ reference.parentUrl,
88
+ ),
89
+ });
90
+ if (filesystemResolution.stat) {
91
+ stat = filesystemResolution.stat;
92
+ url = filesystemResolution.url;
88
93
  }
89
- if (stat && stat.isDirectory()) {
90
- const directoryAllowed =
91
- reference.type === "filesystem" ||
92
- (typeof directoryReferenceAllowed === "function" &&
93
- directoryReferenceAllowed(reference)) ||
94
- directoryReferenceAllowed;
95
- if (!directoryAllowed) {
96
- const error = new Error("Reference leads to a directory");
97
- error.code = "DIRECTORY_REFERENCE_NOT_ALLOWED";
98
- throw error;
99
- }
94
+ }
95
+ if (stat && stat.isDirectory()) {
96
+ const directoryAllowed =
97
+ reference.type === "filesystem" ||
98
+ (typeof directoryReferenceAllowed === "function" &&
99
+ directoryReferenceAllowed(reference)) ||
100
+ directoryReferenceAllowed;
101
+ if (!directoryAllowed) {
102
+ const error = new Error("Reference leads to a directory");
103
+ error.code = "DIRECTORY_REFERENCE_NOT_ALLOWED";
104
+ throw error;
100
105
  }
101
106
  }
102
107
  reference.leadsToADirectory = stat && stat.isDirectory();
@@ -3,14 +3,15 @@ export const jsenvPluginProtocolHttp = () => {
3
3
  name: "jsenv:protocol_http",
4
4
  appliesDuring: "*",
5
5
  redirectReference: (reference) => {
6
+ // TODO: according to some pattern matching jsenv could be allowed
7
+ // to fetch and transform http urls
6
8
  if (
7
9
  reference.url.startsWith("http:") ||
8
10
  reference.url.startsWith("https:")
9
11
  ) {
10
- reference.mustIgnore = true;
12
+ return `ignore:${reference.url}`;
11
13
  }
12
- // TODO: according to some pattern matching jsenv could be allowed
13
- // to fetch and transform http urls
14
+ return null;
14
15
  },
15
16
  };
16
17
  };