Skip to content

Commit c537afb

Browse files
guybedfordMylesBorins
authored andcommitted
module: package "exports" error refinements
Backport-PR-URL: #32610 PR-URL: #31625 Reviewed-By: Jan Krems <[email protected]>
1 parent 05091d4 commit c537afb

File tree

10 files changed

+331
-219
lines changed

10 files changed

+331
-219
lines changed

doc/api/errors.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,12 @@ An invalid HTTP token was supplied.
13011301

13021302
An IP address is not valid.
13031303

1304+
<a id="ERR_INVALID_MODULE_SPECIFIER"></a>
1305+
### `ERR_INVALID_MODULE_SPECIFIER`
1306+
1307+
The imported module string is an invalid URL, package name, or package subpath
1308+
specifier.
1309+
13041310
<a id="ERR_INVALID_OPT_VALUE"></a>
13051311
### `ERR_INVALID_OPT_VALUE`
13061312

@@ -1316,6 +1322,12 @@ An invalid or unknown file encoding was passed.
13161322

13171323
An invalid `package.json` file was found which failed parsing.
13181324

1325+
<a id="ERR_INVALID_PACKAGE_TARGET"></a>
1326+
### `ERR_INVALID_PACKAGE_TARGET`
1327+
1328+
The `package.json` [exports][] field contains an invalid target mapping value
1329+
for the attempted module resolution.
1330+
13191331
<a id="ERR_INVALID_PERFORMANCE_MARK"></a>
13201332
### `ERR_INVALID_PERFORMANCE_MARK`
13211333

@@ -1616,6 +1628,13 @@ A non-context-aware native addon was loaded in a process that disallows them.
16161628

16171629
A given value is out of the accepted range.
16181630

1631+
<a id="ERR_PACKAGE_PATH_NOT_EXPORTED"></a>
1632+
### `ERR_PACKAGE_PATH_NOT_EXPORTED`
1633+
1634+
The `package.json` [exports][] field does not export the requested subpath.
1635+
Because exports are encapsulated, private internal modules that are not exported
1636+
cannot be imported through the package resolution, unless using an absolute URL.
1637+
16191638
<a id="ERR_REQUIRE_ESM"></a>
16201639
### `ERR_REQUIRE_ESM`
16211640

@@ -2457,6 +2476,7 @@ such as `process.stdout.on('data')`.
24572476
[crypto digest algorithm]: crypto.html#crypto_crypto_gethashes
24582477
[domains]: domain.html
24592478
[event emitter-based]: events.html#events_class_eventemitter
2479+
[exports]: esm.html#esm_package_exports
24602480
[file descriptors]: https://en.wikipedia.org/wiki/File_descriptor
24612481
[policy]: policy.html
24622482
[stream-based]: stream.html

doc/api/esm.md

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,17 @@ of these top-level routines unless stated otherwise.
14461446
_defaultEnv_ is the conditional environment name priority array,
14471447
`["node", "import"]`.
14481448
1449+
The resolver can throw the following errors:
1450+
* _Invalid Module Specifier_: Module specifier is an invalid URL, package name
1451+
or package subpath specifier.
1452+
* _Invalid Package Configuration_: package.json configuration is invalid or
1453+
contains an invalid configuration.
1454+
* _Invalid Package Target_: Package exports define a target module within the
1455+
package that is an invalid type or string target.
1456+
* _Package Path Not Exported_: Package exports do not define or permit a target
1457+
subpath in the package for the given module.
1458+
* _Module Not Found_: The package or module requested does not exist.
1459+
14491460
<details>
14501461
<summary>Resolver algorithm specification</summary>
14511462
@@ -1456,7 +1467,7 @@ _defaultEnv_ is the conditional environment name priority array,
14561467
> 1. Set _resolvedURL_ to the result of parsing and reserializing
14571468
> _specifier_ as a URL.
14581469
> 1. Otherwise, if _specifier_ starts with _"/"_, then
1459-
> 1. Throw an _Invalid Specifier_ error.
1470+
> 1. Throw an _Invalid Module Specifier_ error.
14601471
> 1. Otherwise, if _specifier_ starts with _"./"_ or _"../"_, then
14611472
> 1. Set _resolvedURL_ to the URL resolution of _specifier_ relative to
14621473
> _parentURL_.
@@ -1466,7 +1477,7 @@ _defaultEnv_ is the conditional environment name priority array,
14661477
> **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
14671478
> 1. If _resolvedURL_ contains any percent encodings of _"/"_ or _"\\"_ (_"%2f"_
14681479
> and _"%5C"_ respectively), then
1469-
> 1. Throw an _Invalid Specifier_ error.
1480+
> 1. Throw an _Invalid Module Specifier_ error.
14701481
> 1. If _resolvedURL_ does not end with a trailing _"/"_ and the file at
14711482
> _resolvedURL_ does not exist, then
14721483
> 1. Throw a _Module Not Found_ error.
@@ -1480,22 +1491,22 @@ _defaultEnv_ is the conditional environment name priority array,
14801491
> 1. Let _packageName_ be *undefined*.
14811492
> 1. Let _packageSubpath_ be *undefined*.
14821493
> 1. If _packageSpecifier_ is an empty string, then
1483-
> 1. Throw an _Invalid Specifier_ error.
1494+
> 1. Throw an _Invalid Module Specifier_ error.
14841495
> 1. Otherwise,
14851496
> 1. If _packageSpecifier_ does not contain a _"/"_ separator, then
1486-
> 1. Throw an _Invalid Specifier_ error.
1497+
> 1. Throw an _Invalid Module Specifier_ error.
14871498
> 1. Set _packageName_ to the substring of _packageSpecifier_
14881499
> until the second _"/"_ separator or the end of the string.
14891500
> 1. If _packageName_ starts with _"."_ or contains _"\\"_ or _"%"_, then
1490-
> 1. Throw an _Invalid Specifier_ error.
1501+
> 1. Throw an _Invalid Module Specifier_ error.
14911502
> 1. Let _packageSubpath_ be _undefined_.
14921503
> 1. If the length of _packageSpecifier_ is greater than the length of
14931504
> _packageName_, then
14941505
> 1. Set _packageSubpath_ to _"."_ concatenated with the substring of
14951506
> _packageSpecifier_ from the position at the length of _packageName_.
14961507
> 1. If _packageSubpath_ contains any _"."_ or _".."_ segments or percent
14971508
> encoded strings for _"/"_ or _"\\"_, then
1498-
> 1. Throw an _Invalid Specifier_ error.
1509+
> 1. Throw an _Invalid Module Specifier_ error.
14991510
> 1. Set _selfUrl_ to the result of
15001511
> **SELF_REFERENCE_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_).
15011512
> 1. If _selfUrl_ isn't empty, return _selfUrl_.
@@ -1552,7 +1563,7 @@ _defaultEnv_ is the conditional environment name priority array,
15521563
> 1. Throw a _Module Not Found_ error.
15531564
> 1. If _pjson.exports_ is not **null** or **undefined**, then
15541565
> 1. If _exports_ is an Object with both a key starting with _"."_ and a key
1555-
> not starting with _"."_, throw an "Invalid Package Configuration" error.
1566+
> not starting with _"."_, throw an _Invalid Package Configuration_ error.
15561567
> 1. If _pjson.exports_ is a String or Array, or an Object containing no
15571568
> keys starting with _"."_, then
15581569
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
@@ -1561,6 +1572,7 @@ _defaultEnv_ is the conditional environment name priority array,
15611572
> 1. Let _mainExport_ be the _"."_ property in _pjson.exports_.
15621573
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
15631574
> _mainExport_, _""_).
1575+
> 1. Throw a _Package Path Not Exported_ error.
15641576
> 1. If _pjson.main_ is a String, then
15651577
> 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and
15661578
> _pjson.main_.
@@ -1575,7 +1587,7 @@ _defaultEnv_ is the conditional environment name priority array,
15751587
15761588
**PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _packagePath_, _exports_)
15771589
> 1. If _exports_ is an Object with both a key starting with _"."_ and a key not
1578-
> starting with _"."_, throw an "Invalid Package Configuration" error.
1590+
> starting with _"."_, throw an _Invalid Package Configuration_ error.
15791591
> 1. If _exports_ is an Object and all keys of _exports_ start with _"."_, then
15801592
> 1. Set _packagePath_ to _"./"_ concatenated with _packagePath_.
15811593
> 1. If _packagePath_ is a key of _exports_, then
@@ -1591,43 +1603,44 @@ _defaultEnv_ is the conditional environment name priority array,
15911603
> of the length of _directory_.
15921604
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_,
15931605
> _subpath_, _defaultEnv_).
1594-
> 1. Throw a _Module Not Found_ error.
1606+
> 1. Throw a _Package Path Not Exported_ error.
15951607
15961608
**PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_, _env_)
15971609
1598-
> 1. If _target_ is a String, then
1599-
> 1. If _target_ does not start with _"./"_, throw a _Module Not Found_
1600-
> error.
1601-
> 1. If _subpath_ has non-zero length and _target_ does not end with _"/"_,
1602-
> throw a _Module Not Found_ error.
1603-
> 1. If _target_ or _subpath_ contain any _"node_modules"_ segments including
1604-
> _"node_modules"_ percent-encoding, throw a _Module Not Found_ error.
1610+
> 1.If _target_ is a String, then
1611+
> 1. If _target_ does not start with _"./"_ or contains any _"node_modules"_
1612+
> segments including _"node_modules"_ percent-encoding, throw an
1613+
> _Invalid Package Target_ error.
16051614
> 1. Let _resolvedTarget_ be the URL resolution of the concatenation of
16061615
> _packageURL_ and _target_.
1607-
> 1. If _resolvedTarget_ is contained in _packageURL_, then
1608-
> 1. Let _resolved_ be the URL resolution of the concatenation of
1609-
> _subpath_ and _resolvedTarget_.
1610-
> 1. If _resolved_ is contained in _resolvedTarget_, then
1611-
> 1. Return _resolved_.
1616+
> 1. If _resolvedTarget_ is not contained in _packageURL_, throw an
1617+
> _Invalid Package Target_ error.
1618+
> 1. If _subpath_ has non-zero length and _target_ does not end with _"/"_,
1619+
> throw an _Invalid Module Specifier_ error.
1620+
> 1. Let _resolved_ be the URL resolution of the concatenation of
1621+
> _subpath_ and _resolvedTarget_.
1622+
> 1. If _resolved_ is not contained in _resolvedTarget_, throw an
1623+
> _Invalid Module Specifier_ error.
1624+
> 1. Return _resolved_.
16121625
> 1. Otherwise, if _target_ is a non-null Object, then
16131626
> 1. If _exports_ contains any index property keys, as defined in ECMA-262
16141627
> [6.1.7 Array Index][], throw an _Invalid Package Configuration_ error.
16151628
> 1. For each property _p_ of _target_, in object insertion order as,
16161629
> 1. If _env_ contains an entry for _p_, then
16171630
> 1. Let _targetValue_ be the value of the _p_ property in _target_.
1618-
> 1. Let _resolved_ be the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**
1619-
> (_packageURL_, _targetValue_, _subpath_, _env_).
1620-
> 1. Assert: _resolved_ is a String.
1621-
> 1. Return _resolved_.
1631+
> 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(
1632+
> _packageURL_, _targetValue_, _subpath_, _env_), continuing the
1633+
> loop on any _Package Path Not Exported_ error.
1634+
> 1. Throw a _Package Path Not Exported_ error.
16221635
> 1. Otherwise, if _target_ is an Array, then
1636+
> 1. If _target.length is zero, throw an _Invalid Package Target_ error.
16231637
> 1. For each item _targetValue_ in _target_, do
16241638
> 1. If _targetValue_ is an Array, continue the loop.
1625-
> 1. Let _resolved_ be the result of
1626-
> **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _targetValue_,
1627-
> _subpath_, _env_), continuing the loop on abrupt completion.
1628-
> 1. Assert: _resolved_ is a String.
1629-
> 1. Return _resolved_.
1630-
> 1. Throw a _Module Not Found_ error.
1639+
> 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
1640+
> _targetValue_, _subpath_, _env_), continuing the loop on any
1641+
> _Package Path Not Exported_ or _Invalid Package Target_ error.
1642+
> 1. Throw the last fallback resolution error.
1643+
> 1. Otherwise throw an _Invalid Package Target_ error.
16311644
16321645
**ESM_FORMAT**(_url_)
16331646

lib/internal/errors.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,20 @@
1313
const {
1414
ArrayIsArray,
1515
Error,
16+
JSONStringify,
1617
Map,
1718
MathAbs,
1819
NumberIsInteger,
1920
ObjectDefineProperty,
2021
ObjectKeys,
22+
StringPrototypeSlice,
2123
Symbol,
2224
SymbolFor,
2325
WeakMap,
2426
} = primordials;
2527

28+
const sep = process.platform === 'win32' ? '\\' : '/';
29+
2630
const messages = new Map();
2731
const codes = {};
2832

@@ -1065,14 +1069,29 @@ E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError);
10651069
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError);
10661070
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError);
10671071
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError);
1072+
E('ERR_INVALID_MODULE_SPECIFIER', (pkgPath, subpath) => {
1073+
assert(subpath !== '.');
1074+
return `Package subpath '${subpath}' is not a valid module request for the ` +
1075+
`"exports" resolution of ${pkgPath}${sep}package.json`;
1076+
}, TypeError);
10681077
E('ERR_INVALID_OPT_VALUE', (name, value) =>
10691078
`The value "${String(value)}" is invalid for option "${name}"`,
10701079
TypeError,
10711080
RangeError);
10721081
E('ERR_INVALID_OPT_VALUE_ENCODING',
10731082
'The value "%s" is invalid for option "encoding"', TypeError);
10741083
E('ERR_INVALID_PACKAGE_CONFIG',
1075-
'Invalid package config for \'%s\', %s', Error);
1084+
`Invalid package config %s${sep}package.json, %s`, Error);
1085+
E('ERR_INVALID_PACKAGE_TARGET', (pkgPath, key, subpath, target) => {
1086+
if (key === '.') {
1087+
return `Invalid "exports" main target ${JSONStringify(target)} defined ` +
1088+
`in the package config ${pkgPath}${sep}package.json`;
1089+
} else {
1090+
return `Invalid "exports" target ${JSONStringify(target)} defined for '${
1091+
StringPrototypeSlice(key, 0, -subpath.length || key.length)}' in the ` +
1092+
`package config ${pkgPath}${sep}package.json`;
1093+
}
1094+
}, Error);
10761095
E('ERR_INVALID_PERFORMANCE_MARK',
10771096
'The "%s" performance mark has not been set', Error);
10781097
E('ERR_INVALID_PROTOCOL',
@@ -1216,6 +1235,14 @@ E('ERR_OUT_OF_RANGE',
12161235
msg += ` It must be ${range}. Received ${received}`;
12171236
return msg;
12181237
}, RangeError);
1238+
E('ERR_PACKAGE_PATH_NOT_EXPORTED', (pkgPath, subpath) => {
1239+
if (subpath === '.') {
1240+
return `No "exports" main resolved in ${pkgPath}${sep}package.json`;
1241+
} else {
1242+
return `Package subpath '${subpath}' is not defined by "exports" in ${
1243+
pkgPath}${sep}package.json`;
1244+
}
1245+
}, Error);
12191246
E('ERR_REQUIRE_ESM',
12201247
(filename, parentPath = null, packageJsonPath = null) => {
12211248
let msg = `Must use import to load ES Module: ${filename}`;

0 commit comments

Comments
 (0)