Skip to content
This repository has been archived by the owner on Apr 16, 2020. It is now read-only.

Commit

Permalink
specify import file specifier resolution proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Dec 4, 2018
1 parent d473041 commit 09cf19d
Showing 1 changed file with 111 additions and 20 deletions.
131 changes: 111 additions & 20 deletions doc/api/esm.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ property:

## Notable differences between `import` and `require`

### Only Support for .mjs

ESM must have the `.mjs` extension.

### Mandatory file extensions

You must provide a file extension when using the `import` keyword.
Expand Down Expand Up @@ -157,37 +153,132 @@ The resolver has the following properties:
### Resolver Algorithm
The algorithm to resolve an ES module specifier is provided through
_ESM_RESOLVE_:
The algorithm to load an ES module specifier is given through the
**ESM_RESOLVE** method below. It returns the resolved URL for a
module specifier relative to a parentURL, in addition to the unique module
format for that resolved URL given by the **ESM_FORMAT** routine.
In the following algorithms, all subroutine errors are propogated as errors
of these top-level routines.
**ESM_RESOLVE**(_specifier_, _parentURL_)
> 1. Let _resolvedURL_ be _undefined_.
> 1. If _specifier_ is a valid URL then,
#### ESM_RESOLVE(_specifier_, _parentURL_)
> 1. Let _resolvedURL_ be *undefined*.
> 1. If _specifier_ is a valid URL, then
> 1. Set _resolvedURL_ to the result of parsing and reserializing
> _specifier_ as a URL.
> 1. Otherwise, if _specifier_ starts with _"/"_, _"./"_ or _"../"_ then,
> 1. Otherwise, if _specifier_ starts with _"/"_, then
> 1. Throw an _Invalid Specifier_ error.
> 1. Otherwise, if _specifier_ starts with _"./"_ or _"../"_, then
> 1. Set _resolvedURL_ to the URL resolution of _specifier_ relative to
> _parentURL_.
> 1. Otherwise,
> 1. Note: _specifier_ is now a bare specifier.
> 1. Set _resolvedURL_ the result of
> **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
> 1. If the file at _resolvedURL_ does not exist then,
> 1. If the file at _resolvedURL_ does not exist, then
> 1. Throw a _Module Not Found_ error.
> 1. Return _resolvedURL_.
**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
> 1. Assert: _packageSpecifier_ is a bare specifier.
> 1. If _packageSpecifier_ is a Node.js builtin module then,
> 1. Let _format_ be the result of **ESM_FORMAT**(_url_).
> 1. Return _{ resolvedURL, format }_.
PACKAGE_RESOLVE(_packageSpecifier_, _parentURL_)
> 1. Let _packageName_ be *undefined*.
> 1. Let _packagePath_ be *undefined*.
> 1. If _packageSpecifier_ does not start with _"@"_, then
> 1. If _packageSpecifier_ is an empty string, then
> 1. Throw an _Invalid Package Name_ error.
> 1. Set _packageName_ to the substring of _packageSpecifier_ until the
> first _"/"_ separator or the end of the string.
> 1. If _packageSpecifier_ starts with _"@"_, then
> 1. If _packageSpecifier_ does not contain a _"/"_ separator, then
> 1. Throw an _Invalid Package Name_ error.
> 1. Set _packageName_ to the substring of _packageSpecifier_
> until the second _"/"_ separator or the end of the string.
> 1. Let _packagePath_ be the substring of _packageSpecifier_ from the
> position at the length of _packageName_ plus one, if any.
> 1. Assert: _packageName_ is a valid package name or scoped package name.
> 1. Assert: _packagePath_ is either empty, or a path without a leading
> separator.
> 1. Note: Further package name validations can be added here.
> 1. If _packagePath_ is empty and _packageName_ is a Node.js builtin
> module, then
> 1. Return the string _"node:"_ concatenated with _packageSpecifier_.
> 1. While _parentURL_ contains a non-empty _pathname_,
> 1. While _parentURL_ is not the file system root,
> 1. Set _parentURL_ to the parent folder URL of _parentURL_.
> 1. Let _packageURL_ be the URL resolution of the string concatenation of
> _parentURL_, _"/node_modules/"_ and _"packageSpecifier"_.
> 1. If the file at _packageURL_ exists then,
> 1. Return _packageURL_.
> _parentURL_, _"/node_modules/"_ and _packageSpecifier_.
> 1. If the folder at _packageURL_ does not exist, then
> 1. Note: This check can be optimized out where possible in
> implementation.
> 1. Set _parentURL_ to the parent URL path of _parentURL_.
> 1. Continue the next loop iteration.
> 1. If _packagePath_ is empty, then
> 1. Let _url_ be the result of **PACKAGE_MAIN_RESOLVE**(_packageURL_).
> 1. If _url_ is *null*, then
> 1. Throw a _Module Not Found_ error.
> 1. Return _url_.
> 1. Otherwise,
> 1. Return the URL resolution of _packagePath_ in _packageURL_.
> 1. Throw a _Module Not Found_ error.
PACKAGE_MAIN_RESOLVE(_packageURL_)
> 1. Let _pjsonURL_ be the URL of the file _"package.json"_ within the parent
path _packageURL_.
> 1. If the file at _pjsonURL_ exists, then
> 1. Let _pjson_ be the result of **READ_JSON_FILE**(_pjsonURL_).
> 1. If **HAS_ESM_PROPERTIES**(_pjson_) is *true*, then
> 1. Let _mainURL_ be the result applying the legacy
> **LOAD_AS_DIRECTORY** CommonJS resolver to _packageURL_, returning
> *undefined* for no resolution.
> 1. If _mainURL_ is not *undefined* and **ESM_FORMAT**(_mainURL_) is not
> equal to _"cjs"_, then
> 1. Throw a _"Invalid Module Format"_ error.
> 1. Return _mainURL_.
> 1. _Note: ESM main yet to be implemented here._
> 1. Return *null*.
#### ESM_FORMAT(_url_)
> 1. Assert: _url_ corresponds to an existing file.
> 1. Let _pjsonURL_ be the result of **READ_PACKAGE_BOUNDARY**(_url_).
> 1. Let _pjson_ be *undefined*.
> 1. If _pjsonURL_ is not *null*, then
> 1. Set _pjson_ to the result of **READ_JSON_FILE**(_pjsonURL_).
> 1. If _pjsonURL_ is *null* or **HAS_ESM_PROPERTIES**(_pjson_) is *true*, then
> 1. If _url_ does not end in _".js"_ or _".mjs"_ then,
> 1. Throw an _Unkonwn Module Format_ error.
> 1. Return _"esm"_.
> 1. Otherwise,
> 1. If _url_ does not end in _".js"_ then,
> 1. Throw an _Unknown Module Format_ error.
> 1. Return _"cjs"_.
> 1. If **HAS_ESM_PROPERTIES**(_pjson_) is *true*, then
> 1. Return _"esm"_.
> 1. Return _"cjs"_.
READ_PACKAGE_BOUNDARY(_url_)
> 1. Let _boundaryURL_ be the URL resolution of _"package.json"_ relative to
> _url_.
> 1. While _boundaryURL_ is not the file system root,
> 1. If the file at _boundaryURL_ exists, then
> 1. Return _boundaryURL_.
> 1. Set _boundaryURL_ to the URL resolution of _"../package.json"_ relative
> to _boundaryURL_.
> 1. Return *null*.
READ_JSON_FILE(_url_)
> 1. If the file at _url_ does not parse as valid JSON, then
> 1. Throw an _Invalid Package Configuration_ error.
> 1. Let _pjson_ be the parsed JSON source of the file at _url_.
> 1. Return _pjson_.
HAS_ESM_PROPERTIES(_pjson_)
> 1. Note: To be specified.
_ESM properties_ in a package.json file are yet to be specified.
The current possible specifications for this are the
[_"exports"_](https://github.com/jkrems/proposal-pkg-exports)
or [_"mode"_](https://github.com/nodejs/node/pull/18392) flag.
[Node.js EP for ES Modules]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md
[`module.createRequireFromPath()`]: modules.html#modules_module_createrequirefrompath_filename
[ESM Minimal Kernel]: https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md

0 comments on commit 09cf19d

Please sign in to comment.