Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: Resolution algorithm collision #14990

Closed
bmeck opened this issue Aug 23, 2017 · 25 comments
Closed

Regression: Resolution algorithm collision #14990

bmeck opened this issue Aug 23, 2017 · 25 comments
Labels
module Issues and PRs related to the module subsystem.

Comments

@bmeck
Copy link
Member

bmeck commented Aug 23, 2017

  • Version: v4+
  • Platform: all
  • Subsystem: module

At some time just before v4 a seemingly invalid test was introduced. It invalidates the resolve algorithm as documented by checking for ./foo/package.json before ./foo.js when using require('./foo') always.

The intent was for require("..") to prefer a directory instead of doing regular resolution. However, that does not match the documented algorithm which would require a / to invalidate file searching.

I don't have a clear way to explain the current behavior and would like to revert this behavior. We could state that matching /${path_separator}.?./$ at the end of a require specifier would automatically add / but that seems a bit odd.

I want to revert this change.

@jasnell
Copy link
Member

jasnell commented Aug 23, 2017

ping @nodejs/ctc

@jasnell jasnell added ctc-review module Issues and PRs related to the module subsystem. labels Aug 23, 2017
@cjihrig
Copy link
Contributor

cjihrig commented Aug 23, 2017

Is it just a test, or were there changes to the algorithm itself? If it's just a test, could we rework it to be correct? If there were changes to the algorithm, then we might want to update the docs instead.

@bmeck
Copy link
Member Author

bmeck commented Aug 23, 2017

The test is invalid since it doesn't match the docs. We need to revert to the original algorithm to fix. I don't want to update docs because the behavior is very odd to me.

@BridgeAR
Copy link
Member

As far as I see it the test (and code change) exists since iojs 1.0 and was introduced here 36777d2

@bmeck
Copy link
Member Author

bmeck commented Aug 23, 2017

Any way we look at it, we should fix the require("./foo") example above

@jasnell
Copy link
Member

jasnell commented Aug 23, 2017

I'm +1 for reverting but we need to take a close look at the semver-i-iness of the change.

@bnoordhuis
Copy link
Member

bnoordhuis commented Aug 23, 2017

The test is invalid since it doesn't match the docs.

The description in the documentation has been at odds with the implementation since at least v0.12, possibly v0.10. See #4595 (comment) for an example.

@jasnell
Copy link
Member

jasnell commented Aug 23, 2017

@bnoordhuis ... given that, which do you prefer: modifying the docs to match the impl or modifying the impl to match the docs?

@bnoordhuis
Copy link
Member

The path of least resistance is to update the documentation; any change to the algorithm will almost certainly result in some fallout.

@bmeck
Copy link
Member Author

bmeck commented Aug 23, 2017 via email

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

It should be noted that userland implementations of resolution logic like resolve at 800k downloads per day don't exhibit this behavior.

@mcollina
Copy link
Member

@bmeck if that's not too much effort, would you assemble a PR anyway? It is hard to understand the impact of this behaviour without a SHA reference and a full example. I think seeing the actual change you are planning to make would help.

@ljharb
Copy link
Member

ljharb commented Aug 24, 2017

From a user perspective (and resolve maintainer perspective), the current behavior is very very strange, and I'd vastly prefer the (at least) <= 0.8 behavior.

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

Made a PR people an look at.

@mcollina
Copy link
Member

@bmeck do you have a trail on why this change was introduced?

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

@mcollina Unclear on a few quick searches, but the test makes it seem to be because someone had the following:

foo/
   package.json -> main.js
   main.js
   bar/
      baz.js -> require('../..')
foo.js

And baz resolved ../.. to foo.js instead of foo/main.js

@mcollina
Copy link
Member

I do not think we can change that behavior now.

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

@mcollina no userland impl uses this odd behavior.

@mcollina
Copy link
Member

@bmeck definitely. However I fear there is plenty of code that is using that behavior, even in npm and also closed source. This makes it semver-major squared for me, and maybe the ship of changing this has sailed.

Who did the original edits? I would ask to @isaacs what he thinks of this potential change.

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

@mcollina to preserve the nature of the test, we could make trailingSlash set to true whenever resolving a path ending in /. or /..

@bmeck
Copy link
Member Author

bmeck commented Aug 24, 2017

if it matters URL adds trailing slashes:

console.log(new URL('../..', 'file://a/b/c/d').href); // file://a/

@mcollina
Copy link
Member

to preserve the nature of the test, we could make trailingSlash set to true whenever resolving a path ending in /. or /..

@bmeck is this a suggestion to change the behavior or just amend the test?

Bear with me, you are way more familiar with the internal of the module system than myself, and I care that the current behavior is not changed, as I fear breakages. trailingSlash  set to true where?

@bmeck
Copy link
Member Author

bmeck commented Aug 25, 2017

@mcollina in all scenarios, the behavior needs to change due to inconsistencies. See the test in the PR pointing to this issue for an example.

The suggestion above about setting trailingSlash is to make the old test pass while fixing inconsistencies. It would, however, add a minor documentation change and not act 100% the same as before the regression occured.

In particular given the dir structure:

foo/
  bar/
     baz.js
foo.js

If baz.js does require('..'), it would not find foo.js, which it currently does find (but the regression commit/test seems to revolve around loading directory instead of files when using ..).

The behavior of approximately adding a trailing / is nice however since it matched what the URL specification does when resolving with . and .. specifiers. In those cases the URL specification keeps the trailing slash, while node's resolution currently removes the trailing slash.

@mcollina
Copy link
Member

#14990 (comment) I am in favor of what you propose there.

Is that related in #15015? Over there it mentions package.json, but not in the comment above.

@evanlucas
Copy link
Contributor

I think we should revert to the old (and documented) behavior. If there is concern about the ecosystem effects, we could allow it to be an opt-out with a flag?

BridgeAR pushed a commit to bmeck/node that referenced this issue Feb 17, 2018
The documented resolution algorithm was regressed and started to
search for package.json files prior to searching for file extensions
when searching for a specifier. Oddly, it did not search for index
files at same time it searched for package.json. This reverts that
regression and restores the documented behavior of searching for
file extensions prior to searching directories.

Fixes: nodejs#14990
PR-URL: nodejs#15015
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
MayaLekova pushed a commit to MayaLekova/node that referenced this issue May 8, 2018
The documented resolution algorithm started to search for package.json
files prior to searching for file extensions when searching for a
specifier. Oddly, it did not search for index files at same time it
searched for package.json. This restores the documented behavior of
searching for file extensions prior to searching directories.

PR-URL: nodejs#15015
Fixes: nodejs#14990
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Evan Lucas <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Khaidi Chu <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module Issues and PRs related to the module subsystem.
Projects
None yet
Development

No branches or pull requests

9 participants