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

Commit

Permalink
remove main and package parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Nov 7, 2018
1 parent a5f3284 commit 528e26f
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 116 deletions.
72 changes: 4 additions & 68 deletions doc/api/esm.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,36 +154,6 @@ The resolver has the following properties:
* No default extensions
* No folder mains
* Bare specifier package resolution lookup through node_modules
* Avoids the package fallback which breaks package isolation. This is the
problem that an import to `x/y.js` will keep checking subsequent node_modules
even if a package "x" is found without a "y.js". This is done through package
name format detection.
The ESM resolver differs from the CommonJS resolver in detecting a package name
based on it being either `package` or `@scoped/package`. This allows the
resolver to know when a package has been matched, and then avoid a fallback for
missing modules.
The main lookup is then provided by _CHECK_PACKAGE_MAIN_ which is still an
experimental approach under discussion.
Currently, the main lookup will only check for _index.mjs_.
### Examples
Relative and absolute resolution without directory or extension resolution
(URL resolution):
* ESM_RESOLVE("./a.asdf", "file:///parent/path") -> "file:///parent/a.asdf"
* ESM_RESOLVE("/a", "file:///parent/path") -> "file:///a"
* ESM_RESOLVE("file:///a", "file:///parent/path") -> "file:///a"
Package resolution:
1. ESM_RESOLVE("pkg/x", "file:///path/to/project") ->
"file:///path/to/nodemodules/pkg/x" (if it exists)
1. ESM_RESOLVE("pkg/x", "file:///path/to/project") ->
Not Found otherwise, even if "file:///path/nodemodules/pkg/x" exists.
### Resolver Algorithm
Expand All @@ -207,50 +177,16 @@ _ESM_RESOLVE_:
**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
> 1. Assert: _packageSpecifier_ is a bare specifier.
> 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 a _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 a _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. If _packageSpecifier_ is a Node.js builtin module then,
> 1. Return _"node:${packageName}"_.
> 1. Set _parentURL_ to the parent folder URL of _parentURL_.
> 1. While _parentURL_ contains a non-empty _pathname_,
> 1. Let _packageURL_ be the URL resolution of
> _"${parentURL}/node_modules/${packageName}"_.
> 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 _undefined_ then,
> 1. Throw a _Module Not Found_ error.
> 1. Return _url_.
> 1. Otherwise,
> 1. Return the URL resolution of _packagePath_ in _packageURL_.
> _"${parentURL}/node_modules/${packageSpecifier}"_.
> 1. If the file at _packageURL_ exists then,
> 1. Return _packageURL_.
> 1. Throw a _Module Not Found_ error.
**PACKAGE_MAIN_RESOLVE**(_packageURL_)
> 1. Note: Main resolution to be implemented here.
> 1. Return _undefined_.
[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
51 changes: 3 additions & 48 deletions src/module_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -485,60 +485,15 @@ DescriptorType CheckDescriptor(const std::string& path) {
return NONE;
}

inline Maybe<URL> PackageMainResolve(const URL& search) {
return Nothing<URL>();
}

Maybe<URL> PackageResolve(Environment* env,
const std::string& specifier,
const URL& base) {
size_t sep_index = specifier.find('/');
if (specifier[0] == '@' && sep_index == std::string::npos ||
specifier.length() == 0) {
std::string msg = "Invalid package name '" + specifier +
"' imported from " + base.ToFilePath();
node::THROW_ERR_INVALID_PACKAGE_NAME(env, msg.c_str());
return Nothing<URL>();
}
if (specifier[0] == '@') {
sep_index = specifier.find('/', sep_index + 1);
}
std::string pkg_name = specifier.substr(0,
sep_index == std::string::npos ? std::string::npos : sep_index);
std::string pkg_path;
if (sep_index == std::string::npos ||
sep_index == specifier.length() - 1) {
pkg_path = "";
} else {
pkg_path = specifier.substr(sep_index);
}
URL parent(".", base);
std::string last_path;
do {
URL pkg_url("./node_modules/" + pkg_name, &parent);
URL url;
if (pkg_path.length()) {
url = URL("./node_modules/" + pkg_name + pkg_path, &parent);
} else {
url = pkg_url;
}
DescriptorType check;
if (pkg_path.length()) {
DescriptorType check = CheckDescriptor(url.ToFilePath());
if (check == FILE) return Just(url);
if (check == NONE) check = CheckDescriptor(pkg_url.ToFilePath());
} else {
Maybe<URL> main_url = PackageMainResolve(url);
if (!main_url.IsNothing()) return main_url;
check = CheckDescriptor(pkg_url.ToFilePath());
}
// throw not found if we did match a package directory
if (check == DIRECTORY) {
std::string msg = "Cannot find module '" + url.ToFilePath() +
"' imported from " + base.ToFilePath();
node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
return Nothing<URL>();
}
URL pkg_url("./node_modules/" + specifier, &parent);
DescriptorType check = CheckDescriptor(pkg_url.ToFilePath());
if (check == FILE) return Just(pkg_url);
last_path = parent.path();
parent = URL("..", &parent);
// cross-platform root check
Expand Down

0 comments on commit 528e26f

Please sign in to comment.