@jsenv/core 40.5.3 → 40.6.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.
@@ -37,7 +37,28 @@ export const createKitchen = ({
37
37
 
38
38
  ignore,
39
39
  ignoreProtocol = "remove",
40
- supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
40
+ supportedProtocols = [
41
+ "file:",
42
+ "data:",
43
+ // eslint-disable-next-line no-script-url
44
+ "javascript:",
45
+ "virtual:",
46
+ "ignore:",
47
+ "http:",
48
+ "https:",
49
+ "chrome:",
50
+ "chrome-extension:",
51
+ "chrome-untrusted:",
52
+ "isolated-app:",
53
+ ],
54
+ includedProtocols = [
55
+ "file:",
56
+ "data:",
57
+ "virtual:",
58
+ "ignore:",
59
+ "http:",
60
+ "https:",
61
+ ],
41
62
 
42
63
  // during dev/test clientRuntimeCompat is a single runtime
43
64
  // during build clientRuntimeCompat is runtimeCompat
@@ -57,6 +78,9 @@ export const createKitchen = ({
57
78
 
58
79
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
59
80
  const packageConditions = [nodeRuntimeEnabled ? "node" : "browser", "import"];
81
+ if (nodeRuntimeEnabled) {
82
+ supportedProtocols.push("node:");
83
+ }
60
84
 
61
85
  if (packageDependencies === "auto") {
62
86
  packageDependencies = build && nodeRuntimeEnabled ? "ignore" : "include";
@@ -128,8 +152,11 @@ export const createKitchen = ({
128
152
 
129
153
  const isIgnoredByProtocol = (url) => {
130
154
  const { protocol } = new URL(url);
131
- const protocolIsSupported = supportedProtocols.includes(protocol);
132
- return !protocolIsSupported;
155
+ const protocolIsIncluded = includedProtocols.includes(protocol);
156
+ if (protocolIsIncluded) {
157
+ return false;
158
+ }
159
+ return true;
133
160
  };
134
161
  const isIgnoredBecauseInPackageDependencies = (() => {
135
162
  if (packageDependencies === undefined) {
@@ -336,6 +363,21 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
336
363
  }
337
364
  reference.generatedUrl = reference.url;
338
365
  reference.generatedSearchParams = reference.searchParams;
366
+ if (dev) {
367
+ let url = reference.url;
368
+ let { protocol } = new URL(url);
369
+ if (protocol === "ignore:") {
370
+ url = url.slice("ignore:".length);
371
+ protocol = new URL(url, "http://example.com").protocol;
372
+ }
373
+ if (!supportedProtocols.includes(protocol)) {
374
+ const protocolNotSupportedError = new Error(
375
+ `Unsupported protocol "${protocol}" for url "${url}"`,
376
+ );
377
+ protocolNotSupportedError.code = "PROTOCOL_NOT_SUPPORTED";
378
+ throw protocolNotSupportedError;
379
+ }
380
+ }
339
381
  return reference;
340
382
  } catch (error) {
341
383
  throw createResolveUrlError({
@@ -88,6 +88,9 @@ export const jsenvPluginProtocolFile = ({
88
88
  name: "jsenv:directory_as_json",
89
89
  appliesDuring: "*",
90
90
  fetchUrlContent: (urlInfo) => {
91
+ if (!urlInfo.url.startsWith("file:")) {
92
+ return null;
93
+ }
91
94
  const { firstReference } = urlInfo;
92
95
  let { fsStat } = firstReference;
93
96
  if (!fsStat) {
@@ -46,8 +46,7 @@ export const jsenvPluginNodeEsmResolution = (
46
46
  if (config === true) {
47
47
  resolver = nodeEsmResolverDefault;
48
48
  } else if (config === false) {
49
- // resolverMap.set(urlType, () => null);
50
- continue;
49
+ resolver = null;
51
50
  } else if (typeof config === "object") {
52
51
  resolver = resolverFromObject(config, { kitchenContext, urlType });
53
52
  } else {
@@ -62,6 +61,9 @@ export const jsenvPluginNodeEsmResolution = (
62
61
  resolverMap.set(urlType, resolver);
63
62
  }
64
63
  }
64
+ if (!anyTypeResolver) {
65
+ anyTypeResolver = nodeEsmResolverDefault;
66
+ }
65
67
 
66
68
  if (!resolverMap.has("js_module")) {
67
69
  resolverMap.set("js_module", nodeEsmResolverDefault);
@@ -87,8 +89,11 @@ export const jsenvPluginNodeEsmResolution = (
87
89
  }
88
90
  const urlType = urlTypeFromReference(reference);
89
91
  const resolver = resolverMap.get(urlType);
90
- if (resolver) {
91
- return resolver(reference);
92
+ if (resolver !== undefined) {
93
+ if (typeof resolver === "function") {
94
+ return resolver(reference);
95
+ }
96
+ return resolver;
92
97
  }
93
98
  if (anyTypeResolver) {
94
99
  return anyTypeResolver(reference);
@@ -51,13 +51,32 @@ export const createNodeEsmResolver = ({
51
51
  return null; // let it to jsenv_web_resolution
52
52
  }
53
53
  const { specifier } = reference;
54
- const conditions = buildPackageConditions(specifier, parentUrl);
55
- const { url, type, isMain, packageDirectoryUrl } = applyNodeEsmResolution({
54
+ // specifiers like "#something" have a special meaning for Node.js
55
+ // but can also be used in .css and .html files for example and should not be modified
56
+ // by node esm resolution
57
+ const webResolutionFallback =
58
+ ownerUrlInfo.type !== "js_module" ||
59
+ reference.type === "sourcemap_comment";
60
+ const conditions = buildPackageConditions(specifier, parentUrl, {
61
+ webResolutionFallback,
62
+ });
63
+ let resolution;
64
+ const nodeEsmResolutionParams = {
56
65
  conditions,
57
66
  parentUrl,
58
67
  specifier,
59
68
  preservesSymlink,
60
- });
69
+ };
70
+ if (webResolutionFallback) {
71
+ try {
72
+ resolution = applyNodeEsmResolution(nodeEsmResolutionParams);
73
+ } catch {
74
+ return null; // delegate to web_resolution plugin
75
+ }
76
+ } else {
77
+ resolution = applyNodeEsmResolution(nodeEsmResolutionParams);
78
+ }
79
+ const { url, type, isMain, packageDirectoryUrl } = resolution;
61
80
  // try to give a more meaningful filename after build
62
81
  if (isMain && packageDirectoryUrl) {
63
82
  const basename = urlToBasename(url);
@@ -126,12 +145,26 @@ const createBuildPackageConditions = (
126
145
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
127
146
  // https://nodejs.org/api/esm.html#resolver-algorithm-specification
128
147
  const processArgConditions = readCustomConditionsFromProcessArgs();
129
- const devResolver = (specifier, importer) => {
148
+ const devResolver = (specifier, importer, { webResolutionFallback }) => {
130
149
  if (isBareSpecifier(specifier)) {
131
- const { url } = applyNodeEsmResolution({
132
- specifier,
133
- parentUrl: importer,
134
- });
150
+ let url;
151
+ if (webResolutionFallback) {
152
+ try {
153
+ const resolution = applyNodeEsmResolution({
154
+ specifier,
155
+ parentUrl: importer,
156
+ });
157
+ url = resolution.url;
158
+ } catch {
159
+ url = new URL(specifier, importer).href;
160
+ }
161
+ } else {
162
+ const resolution = applyNodeEsmResolution({
163
+ specifier,
164
+ parentUrl: importer,
165
+ });
166
+ url = resolution.url;
167
+ }
135
168
  return !url.includes("/node_modules/");
136
169
  }
137
170
  return !importer.includes("/node_modules/");
@@ -235,12 +268,12 @@ const createBuildPackageConditions = (
235
268
  }
236
269
 
237
270
  const conditionCandidateArray = Object.keys(conditionResolvers);
238
- return (specifier, importer) => {
271
+ return (specifier, importer, params) => {
239
272
  const conditions = [];
240
273
  for (const conditionCandidate of conditionCandidateArray) {
241
274
  const conditionResolver = conditionResolvers[conditionCandidate];
242
275
  if (typeof conditionResolver === "function") {
243
- if (conditionResolver(specifier, importer)) {
276
+ if (conditionResolver(specifier, importer, params)) {
244
277
  conditions.push(conditionCandidate);
245
278
  }
246
279
  } else if (conditionResolver) {