Conversation
| }; | ||
|
|
||
| var defaultPackageIterator = function defaultPackageIterator(x, start, getPackageCandidates, opts) { | ||
| return getPackageCandidates(); |
There was a problem hiding this comment.
Nit: this is really confusing. I saw a function with the same name defined right before this function, which takes 3 arguments. It took me a while to realize that this isn't calling that function, but the one passed as a parameter.
Maybe the one on line 39 could be renamed to getPackageNodeModulesCandidates?
There was a problem hiding this comment.
| return getPackageCandidates(); | |
| return defaultGetPackageCandidates(); |
| }; | ||
|
|
||
| var defaultPackageIterator = function defaultPackageIterator(x, start, getPackageCandidates, opts) { | ||
| return getPackageCandidates(); |
There was a problem hiding this comment.
| return getPackageCandidates(); | |
| return defaultGetPackageCandidates(); |
| return dirs; | ||
| }; | ||
|
|
||
| var defaultPackageIterator = function defaultPackageIterator(x, start, getPackageCandidates, opts) { |
There was a problem hiding this comment.
| var defaultPackageIterator = function defaultPackageIterator(x, start, getPackageCandidates, opts) { | |
| var defaultPackageIterator = function defaultPackageIterator(x, start, defaultGetPackageCandidates, opts) { |
|
@arcanis Is i.e. for |
|
Some context on my last few commits:
|
| var file = path.join(dir, x); | ||
| loadAsFile(file, opts.package, onfile); | ||
| } | ||
| isDirectory(path.dirname(dir), function (err, status) { |
There was a problem hiding this comment.
why the extra path.dirname call? shouldn't the dirs list already have that done?
There was a problem hiding this comment.
dirs may point to files, for example if you do resolve something like foo/package.json then dirs will be ['/n_m/foo/package.json'] (that makes dir a misnomer, do you want me to rename it into entry or similar?).
There was a problem hiding this comment.
i mean, yes, but in that case foo should be the entry that's a directory and package.json should be the entry that's not.
There was a problem hiding this comment.
That's why I call dirname: since dir is /n_m/foo/package.json, the isDir check has to be done against its parent. Even if it was /n_m/foo (which would happen if the request was just foo), the right behavior would be to check against /n_m (since foo is allowed to be a file per the Node resolution rules), so the dirname would still stand.
847d93a to
4d138d7
Compare
|
This is a lot of change in one PR; would you mind opening up a separate PR with all the bugfixes and refactors, and associated tests, so we can get this semver-minor PR as small as possible? |
99aa42e to
c8a6050
Compare
| var dir = dirs[0]; | ||
|
|
||
| isDirectory(dir, isdir); | ||
| isDirectory(path.dirname(dir), isdir); |
There was a problem hiding this comment.
when is the dirname not going to be a directory? the intention here, i believe, is to see if dir points to a file or not. It seems like hoisting the path.join prevents that from being determined.
There was a problem hiding this comment.
The dirname isn't a directory when it doesn't exist. From what I gather from #190 and #116, this code was only meant to speed up the resolution by checking whether the n_m folder existed before doing the file stat calls.
Checking whether the parent of the subpath (ie /n_m/foo for foo/hello) exists has the same behaviours: if foo/hello can be resolved, then /n_m/foo will necessarily be a directory.
There was a problem hiding this comment.
In other words:
| request | partial resolution | isDirectory (before) | isDirectory (after) |
|---|---|---|---|
foo |
/n_m/foo |
/n_m |
/n_m |
foo/bar |
/n_m/foo/bar |
/n_m |
/n_m/foo |
@foo/bar |
/n_m/@foo/bar |
/n_m |
/n_m/@foo |
The effect will be the same before and after: the two stat calls that the code would have made before #190 (taking the first line as an example, one to check whether /n_m/foo.js exists and another to check whether /n_m/foo/index.js exists) won't be necessary because resolve is able to find out that the directory supposed to contain them doesn't even exist.
There was a problem hiding this comment.
I see. Do you think that this perf improvement could also be split out into a separate PR (or even just a separate commit prior to your addition)?
There was a problem hiding this comment.
In this PR it's not a perf improvement, it's necessary to make my PR work with the changes brought by #190 (because with my PR we don't have access to n_m paths anymore in loadNodeModules - instead we only have /n_m/<subpath>). I guess I could revert it and re-apply it, but I'm not sure it would be much clearer 🤔
There was a problem hiding this comment.
I'm mainly concerned about an unintentional breakage, and my hope would be to release this particular change as a patch prior to releasing this PR as a minor.
There was a problem hiding this comment.
I think #190 has only been released in the 2.0.0-next.0 branch, so for the purpose of the patch release the path.dirname thing can be removed entirely. Do you want me to open a separate PR against the 1.x branch?
| }; | ||
|
|
||
| var getPackageCandidates = function getPackageCandidates(x, start, opts) { | ||
| var dirs = nodeModulesPaths(start, opts, x); |
There was a problem hiding this comment.
Since this function is the same in sync.js, maybe it could be extracted to a separate file?
There was a problem hiding this comment.
I thought about that, but then it's a separate file that has to be supported for the rest of v1.
ljharb
left a comment
There was a problem hiding this comment.
Hopefully the backport into 1.x won't be too tricky.
c8a6050 to
0f698c6
Compare
v1.15.0 - [New] `sync`'/`async`: Implement `packageIterator` (#205) - [Refactor] `sync`: add function name - [Refactor] remove useless `exports` assignment - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`
Changes since v2.0.0-next.0: - [Breaking] add ESM wrapper to "exports"; change paths to match - [Breaking] add "exports" to `package.json` Including all changes in v1.14.2 and v1.15.0: - [New] `sync`'/`async`: Implement `packageIterator` (#205) - [Fix] `sync`/`async`: Fixes isCore check (#206) - [Refactor] `sync`: add function name - [Refactor] remove useless `exports` assignment - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`
Offers a fix for the problem described in #199 (comment)
This PR offers a way to alter the default package path generation. The default implementation still uses
path.join('/.../node_modules', packageName)(which cannot work for PnP when using the link protocol for the reasons described here), but the PnP resolver (automatically configured thanks to #174) will directly return the path to the package regardless of the dependency type, shortcutting the default logic.One big advantage of this diff is that it's semver-minor, which avoids having to upgrade all third-party consumers (which I really don't have the bandwidth to do 😅).