Skip to content

Commit 9112b14

Browse files
guybedfordtargos
authored andcommitted
module: exports not exported for null resolutions
PR-URL: #32838 Reviewed-By: Jan Krems <jan.krems@gmail.com>
1 parent 958ff15 commit 9112b14

File tree

5 files changed

+24
-11
lines changed

5 files changed

+24
-11
lines changed

doc/api/esm.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1671,13 +1671,15 @@ The resolver can throw the following errors:
16711671
> loop on any _Package Path Not Exported_ error.
16721672
> 1. Throw a _Package Path Not Exported_ error.
16731673
> 1. Otherwise, if _target_ is an Array, then
1674-
> 1. If _target.length is zero, throw an _Invalid Package Target_ error.
1674+
> 1. If _target.length is zero, throw a _Package Path Not Exported_ error.
16751675
> 1. For each item _targetValue_ in _target_, do
16761676
> 1. If _targetValue_ is an Array, continue the loop.
16771677
> 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
16781678
> _targetValue_, _subpath_, _env_), continuing the loop on any
16791679
> _Package Path Not Exported_ or _Invalid Package Target_ error.
16801680
> 1. Throw the last fallback resolution error.
1681+
> 1. Otherwise, if _target_ is _null_, throw a _Package Path Not Exported_
1682+
> error.
16811683
> 1. Otherwise throw an _Invalid Package Target_ error.
16821684
16831685
**ESM_FORMAT**(_url_)

lib/internal/modules/cjs/loader.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -553,21 +553,22 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
553553
, 0, -1), mappingKey);
554554
} else if (ArrayIsArray(target)) {
555555
if (target.length === 0)
556-
throw new ERR_INVALID_PACKAGE_TARGET(StringPrototypeSlice(baseUrl.pathname
557-
, 0, -1), mappingKey, subpath, target);
556+
throw new ERR_PACKAGE_PATH_NOT_EXPORTED(
557+
StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath);
558+
let lastException;
558559
for (const targetValue of target) {
559560
try {
560561
return resolveExportsTarget(baseUrl, targetValue, subpath, mappingKey);
561562
} catch (e) {
563+
lastException = e;
562564
if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' &&
563565
e.code !== 'ERR_INVALID_PACKAGE_TARGET')
564566
throw e;
565567
}
566568
}
567569
// Throw last fallback error
568-
resolveExportsTarget(baseUrl, target[target.length - 1], subpath,
569-
mappingKey);
570-
assert(false);
570+
assert(lastException !== undefined);
571+
throw lastException;
571572
} else if (typeof target === 'object' && target !== null) {
572573
const keys = ObjectKeys(target);
573574
if (keys.some(isArrayIndex)) {
@@ -596,6 +597,9 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
596597
}
597598
throw new ERR_PACKAGE_PATH_NOT_EXPORTED(
598599
StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath);
600+
} else if (target === null) {
601+
throw new ERR_PACKAGE_PATH_NOT_EXPORTED(
602+
StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey + subpath);
599603
}
600604
throw new ERR_INVALID_PACKAGE_TARGET(
601605
StringPrototypeSlice(baseUrl.pathname, 0, -1), mappingKey, subpath, target);

lib/internal/modules/esm/resolve.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const {
1616
StringPrototypeStartsWith,
1717
StringPrototypeSubstr,
1818
} = primordials;
19-
19+
const assert = require('internal/assert');
2020
const internalFS = require('internal/fs/utils');
2121
const { NativeModule } = require('internal/bootstrap/loaders');
2222
const {
@@ -345,7 +345,7 @@ function resolveExportsTarget(
345345
return finalizeResolution(resolved, base);
346346
} else if (ArrayIsArray(target)) {
347347
if (target.length === 0)
348-
throwExportsInvalid(packageSubpath, target, packageJSONUrl, base);
348+
throwExportsNotFound(packageSubpath, packageJSONUrl, base);
349349

350350
let lastException;
351351
for (let i = 0; i < target.length; i++) {
@@ -366,6 +366,7 @@ function resolveExportsTarget(
366366

367367
return finalizeResolution(resolved, base);
368368
}
369+
assert(lastException !== undefined);
369370
throw lastException;
370371
} else if (typeof target === 'object' && target !== null) {
371372
const keys = ObjectGetOwnPropertyNames(target);
@@ -392,6 +393,8 @@ function resolveExportsTarget(
392393
}
393394
}
394395
throwExportsNotFound(packageSubpath, packageJSONUrl, base);
396+
} else if (target === null) {
397+
throwExportsNotFound(packageSubpath, packageJSONUrl, base);
395398
}
396399
throwExportsInvalid(packageSubpath, target, packageJSONUrl, base);
397400
}

test/es-module/test-esm-exports.mjs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
6565
// Conditional exports with no match are "not exported" errors
6666
['pkgexports/invalid1', './invalid1'],
6767
['pkgexports/invalid4', './invalid4'],
68+
// Null mapping
69+
['pkgexports/null', './null'],
70+
['pkgexports/null/subpath', './null/subpath'],
71+
// Empty fallback
72+
['pkgexports/nofallback1', './nofallback1'],
6873
]);
6974

7075
const invalidExports = new Map([
@@ -75,13 +80,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
7580
['pkgexports/belowdir/pkgexports/asdf.js', './belowdir/'],
7681
// This target file steps below the package
7782
['pkgexports/belowfile', './belowfile'],
78-
// Invalid target handling
79-
['pkgexports/null', './null'],
83+
// Invalid targets
8084
['pkgexports/invalid2', './invalid2'],
8185
['pkgexports/invalid3', './invalid3'],
8286
['pkgexports/invalid5', 'invalid5'],
8387
// Missing / invalid fallbacks
84-
['pkgexports/nofallback1', './nofallback1'],
8588
['pkgexports/nofallback2', './nofallback2'],
8689
// Reaching into nested node_modules
8790
['pkgexports/nodemodules', './nodemodules'],

test/fixtures/node_modules/pkgexports/package.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)