@@ -242,13 +242,13 @@ throw when an attempt is made to import them:
242242
243243``` js
244244import submodule from ' es-module-package/private-module.js' ;
245- // Throws - Package exports error
245+ // Throws - Module not found
246246```
247247
248248> Note: this is not a strong encapsulation as any private modules can still be
249249> loaded by absolute paths.
250250
251- Folders can also be mapped with package exports as well :
251+ Folders can also be mapped with package exports:
252252
253253<!-- eslint-skip -->
254254``` js
@@ -268,8 +268,24 @@ import feature from 'es-module-package/features/x.js';
268268If a package has no exports, setting ` "exports": false ` can be used instead of
269269` "exports": {} ` to indicate the package does not intend for submodules to be
270270exposed.
271- This is just a convention that works because ` false ` , just like ` {} ` , has no
272- iterable own properties.
271+
272+ Any invalid exports entries will be ignored. This includes exports not
273+ starting with ` "./" ` or a missing trailing ` "/" ` for directory exports.
274+
275+ Array fallback support is provided for exports, similarly to import maps
276+ in order to be forward-compatible with fallback workflows in future:
277+
278+ <!-- eslint-skip -->
279+ ``` js
280+ {
281+ " exports" : {
282+ " ./submodule" : [" not:valid" , " ./submodule.js" ]
283+ }
284+ }
285+ ```
286+
287+ Since ` "not:valid" ` is not a supported target, ` "./submodule.js" ` is used
288+ instead as the fallback, as if it were the only target.
273289
274290## <code >import</code > Specifiers
275291
@@ -660,7 +676,7 @@ CommonJS loader. Additional formats such as _"addon"_ can be extended in future
660676updates.
661677
662678In the following algorithms, all subroutine errors are propagated as errors
663- of these top-level routines.
679+ of these top-level routines unless stated otherwise .
664680
665681_isMain_ is **true** when resolving the Node.js application entry point.
666682
@@ -681,6 +697,9 @@ _isMain_ is **true** when resolving the Node.js application entry point.
681697> 1. Note: _specifier_ is now a bare specifier.
682698> 1. Set _resolvedURL_ the result of
683699> **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
700+ > 1. If _resolvedURL_ contains any percent encodings of _"/"_ or _"\\ "_ (_"%2f"_
701+ > and _"%5C"_ respectively), then
702+ > 1. Throw an _Invalid Specifier_ error.
684703> 1. If the file at _resolvedURL_ does not exist, then
685704> 1. Throw a _Module Not Found_ error.
686705> 1. Set _resolvedURL_ to the real path of _resolvedURL_.
@@ -737,7 +756,7 @@ _isMain_ is **true** when resolving the Node.js application entry point.
737756> 1. If _pjson_ is **null**, then
738757> 1. Throw a _Module Not Found_ error.
739758> 1. If _pjson.main_ is a String, then
740- > 1. Let _resolvedMain_ be the concatenation of _packageURL_, "/", and
759+ > 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and
741760> _pjson.main_.
742761> 1. If the file at _resolvedMain_ exists, then
743762> 1. Return _resolvedMain_.
@@ -746,28 +765,49 @@ _isMain_ is **true** when resolving the Node.js application entry point.
746765> 1. Let _legacyMainURL_ be the result applying the legacy
747766> **LOAD_AS_DIRECTORY** CommonJS resolver to _packageURL_, throwing a
748767> _Module Not Found_ error for no resolution.
749- > 1. If _legacyMainURL_ does not end in _".js"_ then,
750- > 1. Throw an _Unsupported File Extension_ error.
751768> 1. Return _legacyMainURL_.
752769
753770**PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _packagePath_, _exports_)
754771> 1. If _exports_ is an Object, then
755772> 1. Set _packagePath_ to _"./"_ concatenated with _packagePath_.
756773> 1. If _packagePath_ is a key of _exports_, then
757774> 1. Let _target_ be the value of _exports[packagePath]_.
758- > 1. If _target_ is not a String, continue the loop.
759- > 1. Return the URL resolution of the concatenation of _packageURL_ and
760- > _target_.
775+ > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_,
776+ > _""_).
761777> 1. Let _directoryKeys_ be the list of keys of _exports_ ending in
762778> _"/"_, sorted by length descending.
763779> 1. For each key _directory_ in _directoryKeys_, do
764780> 1. If _packagePath_ starts with _directory_, then
765781> 1. Let _target_ be the value of _exports[directory]_.
766- > 1. If _target_ is not a String, continue the loop.
767782> 1. Let _subpath_ be the substring of _target_ starting at the index
768783> of the length of _directory_.
769- > 1. Return the URL resolution of the concatenation of _packageURL_,
770- > _target_ and _subpath_.
784+ > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_,
785+ > _subpath_).
786+ > 1. Throw a _Module Not Found_ error.
787+
788+ **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_)
789+ > 1. If _target_ is a String, then
790+ > 1. If _target_ does not start with _"./"_, throw a _Module Not Found_
791+ > error.
792+ > 1. If _subpath_ has non-zero length and _target_ does not end with _"/"_,
793+ > throw a _Module Not Found_ error.
794+ > 1. If _target_ or _subpath_ contain any _"node_modules"_ segments including
795+ > _"node_modules"_ percent-encoding, throw a _Module Not Found_ error.
796+ > 1. Let _resolvedTarget_ be the URL resolution of the concatenation of
797+ > _packageURL_ and _target_.
798+ > 1. If _resolvedTarget_ is contained in _packageURL_, then
799+ > 1. Let _resolved_ be the URL resolution of the concatenation of
800+ > _subpath_ and _resolvedTarget_.
801+ > 1. If _resolved_ is contained in _resolvedTarget_, then
802+ > 1. Return _resolved_.
803+ > 1. Otherwise, if _target_ is an Array, then
804+ > 1. For each item _targetValue_ in _target_, do
805+ > 1. If _targetValue_ is not a String, continue the loop.
806+ > 1. Let _resolved_ be the result of
807+ > **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _targetValue_,
808+ > _subpath_), continuing the loop on abrupt completion.
809+ > 1. Assert: _resolved_ is a String.
810+ > 1. Return _resolved_.
771811> 1. Throw a _Module Not Found_ error.
772812
773813**ESM_FORMAT**(_url_, _isMain_)
@@ -790,6 +830,7 @@ _isMain_ is **true** when resolving the Node.js application entry point.
790830**READ_PACKAGE_SCOPE**(_url_)
791831> 1. Let _scopeURL_ be _url_.
792832> 1. While _scopeURL_ is not the file system root,
833+ > 1. If _scopeURL_ ends in a _"node_modules"_ path segment, return **null**.
793834> 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_scopeURL_).
794835> 1. If _pjson_ is not **null**, then
795836> 1. Return _pjson_.
0 commit comments