@@ -55,10 +55,6 @@ property:
5555
5656## Notable differences between ` import ` and ` require `
5757
58- ### Only Support for .mjs
59-
60- ESM must have the ` .mjs ` extension.
61-
6258### Mandatory file extensions
6359
6460You must provide a file extension when using the ` import ` keyword.
@@ -157,37 +153,128 @@ The resolver has the following properties:
157153
158154### Resolver Algorithm
159155
160- The algorithm to resolve an ES module specifier is provided through
161- _ESM_RESOLVE_:
156+ The algorithm to load an ES module specifier is given through the
157+ **ESM_RESOLVE** method below. It returns the resolved URL for a
158+ module specifier relative to a parentURL, in addition to the unique module
159+ format for that resolved URL given by the **ESM_FORMAT** routine.
160+
161+ The _"esm"_ format is returned for an ECMAScript Module, while the
162+ _"legacy"_ format is used to indicate loading through the legacy
163+ CommonJS loader. Additional formats such as _"wasm"_ or _"addon"_ can be
164+ extended in future updates.
162165
163- **ESM_RESOLVE**(_specifier_, _parentURL_)
164- > 1. Let _resolvedURL_ be _undefined_.
165- > 1. If _specifier_ is a valid URL then,
166+ In the following algorithms, all subroutine errors are propogated as errors
167+ of these top-level routines.
168+
169+ _isMain_ is **true** when resolving the Node.js application entry point.
170+
171+ **ESM_RESOLVE(_specifier_, _parentURL_, _isMain_)**
172+ > 1. Let _resolvedURL_ be **undefined**.
173+ > 1. If _specifier_ is a valid URL, then
166174> 1. Set _resolvedURL_ to the result of parsing and reserializing
167175> _specifier_ as a URL.
168- > 1. Otherwise, if _specifier_ starts with _"/"_, _"./"_ or _"../"_ then,
176+ > 1. Otherwise, if _specifier_ starts with _"/"_, then
177+ > 1. Throw an _Invalid Specifier_ error.
178+ > 1. Otherwise, if _specifier_ starts with _"./"_ or _"../"_, then
169179> 1. Set _resolvedURL_ to the URL resolution of _specifier_ relative to
170180> _parentURL_.
171181> 1. Otherwise,
172182> 1. Note: _specifier_ is now a bare specifier.
173183> 1. Set _resolvedURL_ the result of
174184> **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
175- > 1. If the file at _resolvedURL_ does not exist then,
185+ > 1. If the file at _resolvedURL_ does not exist, then
176186> 1. Throw a _Module Not Found_ error.
177- > 1. Return _resolvedURL_.
178-
179- **PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
180- > 1. Assert: _packageSpecifier_ is a bare specifier.
181- > 1. If _packageSpecifier_ is a Node.js builtin module then,
187+ > 1. Let _format_ be the result of **ESM_FORMAT**(_url_, _isMain_).
188+ > 1. Load _resolvedURL_ as module format, _format_.
189+
190+ PACKAGE_RESOLVE(_packageSpecifier_, _parentURL_)
191+ > 1. Let _packageName_ be *undefined*.
192+ > 1. Let _packageSubpath_ be *undefined*.
193+ > 1. If _packageSpecifier_ is an empty string, then
194+ > 1. Throw an _Invalid Specifier_ error.
195+ > 1. If _packageSpecifier_ does not start with _"@"_, then
196+ > 1. Set _packageName_ to the substring of _packageSpecifier_ until the
197+ > first _"/"_ separator or the end of the string.
198+ > 1. Otherwise,
199+ > 1. If _packageSpecifier_ does not contain a _"/"_ separator, then
200+ > 1. Throw an _Invalid Specifier_ error.
201+ > 1. Set _packageName_ to the substring of _packageSpecifier_
202+ > until the second _"/"_ separator or the end of the string.
203+ > 1. Let _packageSubpath_ be the substring of _packageSpecifier_ from the
204+ > position at the length of _packageName_ plus one, if any.
205+ > 1. Assert: _packageName_ is a valid package name or scoped package name.
206+ > 1. Assert: _packageSubpath_ is either empty, or a path without a leading
207+ > separator.
208+ > 1. If _packageSubpath_ contains any _"."_ or _".."_ segments or percent
209+ > encoded strings for _"/"_ or _"\" _ then,
210+ > 1. Throw an _Invalid Specifier_ error.
211+ > 1. If _packageSubpath_ is empty and _packageName_ is a Node.js builtin
212+ > module, then
182213> 1. Return the string _"node:"_ concatenated with _packageSpecifier_.
183- > 1. While _parentURL_ contains a non-empty _pathname_ ,
214+ > 1. While _parentURL_ is not the file system root ,
184215> 1. Set _parentURL_ to the parent folder URL of _parentURL_.
185216> 1. Let _packageURL_ be the URL resolution of the string concatenation of
186- > _parentURL_, _"/node_modules/"_ and _"packageSpecifier"_.
187- > 1. If the file at _packageURL_ exists then,
188- > 1. Return _packageURL_.
217+ > _parentURL_, _"/node_modules/"_ and _packageSpecifier_.
218+ > 1. If the folder at _packageURL_ does not exist, then
219+ > 1. Set _parentURL_ to the parent URL path of _parentURL_.
220+ > 1. Continue the next loop iteration.
221+ > 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_).
222+ > 1. If _packageSubpath_ is empty, then
223+ > 1. Return the result of **PACKAGE_MAIN_RESOLVE**(_packageURL_,
224+ > _pjson_).
225+ > 1. Otherwise,
226+ > 1. Return the URL resolution of _packageSubpath_ in _packageURL_.
189227> 1. Throw a _Module Not Found_ error.
190228
229+ PACKAGE_MAIN_RESOLVE(_packageURL_, _pjson_)
230+ > 1. If _pjson_ is **null**, then
231+ > 1. Throw a _Module Not Found_ error.
232+ > 1. If _pjson.main_ is a String, then
233+ > 1. Let _resolvedMain_ be the concatenation of _packageURL_, "/", and
234+ > _pjson.main_.
235+ > 1. If the file at _resolvedMain_ exists, then
236+ > 1. Return _resolvedMain_.
237+ > 1. If _pjson.type_ is equal to _"esm"_, then
238+ > 1. Throw a _Module Not Found_ error.
239+ > 1. Let _legacyMainURL_ be the result applying the legacy
240+ > **LOAD_AS_DIRECTORY** CommonJS resolver to _packageURL_, throwing a
241+ > _Module Not Found_ error for no resolution.
242+ > 1. If _legacyMainURL_ does not end in _".js"_ then,
243+ > 1. Throw an _Unsupported File Extension_ error.
244+ > 1. Return _legacyMainURL_.
245+
246+ **ESM_FORMAT(_url_, _isMain_)**
247+ > 1. Assert: _url_ corresponds to an existing file.
248+ > 1. Let _pjson_ be the result of **READ_PACKAGE_BOUNDARY**(_url_).
249+ > 1. If _pjson_ is **null** and _isMain_ is **true**, then
250+ > 1. Return _"legacy"_.
251+ > 1. If _pjson.type_ exists and is _"esm"_, then
252+ > 1. If _url_ does not end in _".js"_ or _".mjs"_, then
253+ > 1. Throw an _Unsupported File Extension_ error.
254+ > 1. Return _"esm"_.
255+ > 1. Otherwise,
256+ > 1. If _url_ ends in _".mjs"_, then
257+ > 1. Return _"esm"_.
258+ > 1. Otherwise,
259+ > 1. Return _"legacy"_.
260+
261+ READ_PACKAGE_BOUNDARY(_url_)
262+ > 1. Let _boundaryURL_ be _url_.
263+ > 1. While _boundaryURL_ is not the file system root,
264+ > 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_boundaryURL_).
265+ > 1. If _pjson_ is not **null**, then
266+ > 1. Return _pjson_.
267+ > 1. Set _boundaryURL_ to the parent URL of _boundaryURL_.
268+ > 1. Return **null**.
269+
270+ READ_PACKAGE_JSON(_packageURL_)
271+ > 1. Let _pjsonURL_ be the resolution of _"package.json"_ within _packageURL_.
272+ > 1. If the file at _pjsonURL_ does not exist, then
273+ > 1. Return **null**.
274+ > 1. If the file at _packageURL_ does not parse as valid JSON, then
275+ > 1. Throw an _Invalid Package Configuration_ error.
276+ > 1. Return the parsed JSON source of the file at _pjsonURL_.
277+
191278[Node.js EP for ES Modules]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md
192279[` module .createRequireFromPath ()` ]: modules.html#modules_module_createrequirefrompath_filename
193280[ESM Minimal Kernel]: https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md
0 commit comments