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

>=1.6.2 break require('.') with NODE_PATH #1356

Closed
a8m opened this issue Apr 6, 2015 · 36 comments
Closed

>=1.6.2 break require('.') with NODE_PATH #1356

a8m opened this issue Apr 6, 2015 · 36 comments
Labels
module Issues and PRs related to the module subsystem.

Comments

@a8m
Copy link

a8m commented Apr 6, 2015

Running iojs until >=v.1.6.1 allow to use require('.')(i.e: index.js) with NODE_PATH.
Using >=v1.6.2 throw an error.

Example:

$ NODE_PATH=src node

// Start repl

> require('.')
Error: Cannot find module '.'
...
...

Could anyone please confirm this regression, so I could work on a fix.
Thx

@mscdex mscdex added confirmed-bug Issues with confirmed bugs. module Issues and PRs related to the module subsystem. labels Apr 6, 2015
@a0viedo
Copy link
Member

a0viedo commented Apr 6, 2015

I can't reproduce this in v1.6.3 nor v1.6.2. With v1.6.1 and v1.6.0 it throws the error Cannot find module '.'

@Fishrock123
Copy link
Contributor

@a8m Are you trying to load a file whose whole name is .?

as of v1.6.2 require('.') works the same as require('./').
6fc5e95

@a8m
Copy link
Author

a8m commented Apr 6, 2015

@a8m Are you trying to load a file whose whole name is .?

No, require('.') means require('index'), i.e: directory.

note that it's throw an error only when running node with NODE_PATH, and it works fine in <=1.6.1.
(please see the example above)

@Fishrock123
Copy link
Contributor

note that it's throw an error only when running node with NODE_PATH, and it works fine in <=1.6.1.
(please see the example above)

It should not work before io.js 1.6.2 because the commit which added the functionality is only in 1.6.2+ -- 6fc5e95

@a8m
Copy link
Author

a8m commented Apr 6, 2015

Can you please run the example above @Fishrock123 ? (it also works on node 0.10)

@rlidwka
Copy link
Contributor

rlidwka commented Apr 6, 2015

No, require('.') means require('index') as I know.

require('.') means "require current directory". Same as require('./').

Works for me as expected:

$ cat > index.js
module.exports=1337
$ NODE_PATH=whatever iojs 
> require('.')
1337

@Fishrock123 Fishrock123 removed the confirmed-bug Issues with confirmed bugs. label Apr 6, 2015
@silverwind
Copy link
Contributor

Well it looks like this was another undocumented feature, but it is a regression. Before the change one could do NODE_PATH=module iojs -p "require('.')" and get the equivalent of require('./module').

@silverwind silverwind added the confirmed-bug Issues with confirmed bugs. label Apr 6, 2015
@a8m
Copy link
Author

a8m commented Apr 6, 2015

On which version are you testing it ? @rlidwka

@silverwind
Copy link
Contributor

This 'feature' looks to be broken by simply setting more than one path in NODE_PATH:

On 1.6.1 (with both module1 and module2 being folders in the current dir):

$ export NODE_PATH=module1,module2
$ iojs -p 'require(".")'
module.js:318
    throw err;
          ^
Error: Cannot find module '.'

Not sure if it's worth to fix, considering it is undocumented and won't work with more than one module dir specified.

@Fishrock123
Copy link
Contributor

@a8m what is the use-case for the previous behavior?

@silverwind
Copy link
Contributor

I'm leaning towards that the current behaviour logically more correct, and would consider the old behavior as a bug, because you'd expect that require('.') would get you the module in $PWD and not the module in the first (and only) path in $NODE_PATH.

Also, $NODE_PATH seems not to be intended to actually contain a module in its root, but subdirectories with modules.

@silverwind silverwind removed the confirmed-bug Issues with confirmed bugs. label Apr 6, 2015
@a8m
Copy link
Author

a8m commented Apr 6, 2015

@a8m what is the use-case for the previous behavior?

here's a travis example, I hope this demonstrate it well.

@a8m
Copy link
Author

a8m commented Apr 6, 2015

@silverwind PTAL in the example above.

@Fishrock123
Copy link
Contributor

Shouldn't require('.') require the directory at src and thus index.js? I suspect something is still a little funny here.

@a8m
Copy link
Author

a8m commented Apr 6, 2015

I suspect something is still a little funny here.

Agree, but patch version should not break the compatibility. and it does.

@silverwind
Copy link
Contributor

@a8m The previous behaviour was probably never intended to work as it did. What if NODE_PATH contains multiple paths to dirs containing index.js each (which in itself isn't really correct usage of NODE_PATH). Should we just resolve . to the first path and replicate the old bugged behaviour when more than one path is specified?

Also, note that NODE_PATH should contain absolute paths as stated to the docs.

@a8m
Copy link
Author

a8m commented Apr 6, 2015

The previous behaviour was probably never intended to work as it did.

Agree, but this "feature" works since >=v0.10, and now(>=1.6.2) it break the compatibility.
this make people's build to suddenly stop working and make them waste time tracking down the issue to fix it.

Also, note that NODE_PATH should contain absolute paths as stated to the docs.

I know, but this happens in both situations.

@silverwind
Copy link
Contributor

Well, I doubt this usage is really widespread, but I a fix could be to check if NODE_PATH contains a single entry as well as that entry to contain a module directly in its root. In that case, '.' could resolve to that path.

If we do a fix as described above, we should deprecate this usage asap :)

@bnoordhuis
Copy link
Member

I'm not a fan of workarounds, especially not when it comes to the module system. I suggest reverting the change and relanding it in v2.x in a few months time if the consensus still is that it's a useful change.

@tellnes
Copy link
Contributor

tellnes commented Apr 7, 2015

+1 on reverting and landing in next branch.

@brendanashworth
Copy link
Contributor

I also vote on a revert, as the module system shouldn't have these sorts of breaking changes.

@brendanashworth
Copy link
Contributor

Ref: #1185

@rvagg
Copy link
Member

rvagg commented Apr 7, 2015

perhaps for 2.0 we should finally put the nail in the NODE_PATH coffin, people new to Node in the last 2 years probably aren't even aware of that "feature"

@monsanto
Copy link
Contributor

monsanto commented Apr 7, 2015

I can't understand the calls for revert. This is a super duper edge case, and it was known at the time of applying the require('.') patch that--surprise--the behavior of require('.') was going to subtly change. The churn of the patch, the revert, and applying the patch again dwarfs the trouble of making someone fix their application that they need to fix anyway.

I have no stake in this particular issue, I just don't want to set a precedent for iojs of reverting intentional changes at the drop of a hat. It would be nice to know if I see something cool in the changelog, that I can count on it being available a month later. If you are going to change the behavior, stick to it.

@rvagg
Copy link
Member

rvagg commented Apr 7, 2015

I agree @monsanto, reverting is my least favourite option here by far

@a8m
Copy link
Author

a8m commented Apr 7, 2015

Thanks @monsanto

This is issue in not about the design of require, if it's good or bad practice, or how to use it.
It's about regression.
This break people's production code, and it shouldn't.(at least in a patch-version).

For this reason, I'll be +1 on reverting and landing it in v2.0.

@petkaantonov
Copy link
Contributor

This break people's production code, and it shouldn't.(at least in a patch-version).

This is preposterous because this issue scores all three of:

  1. Affects a very small amount of users
  2. Is not an intended feature, might even be a bug
  3. Is trivial to fix for the affected users

Strictest semver would not consider these at all which means every change, no matter what, must increment a major which would obviously make it pointless to use the scheme in the first place.

Therefore in practice when something follows a semver, it doesn't follow it strictly but considers some combination of the factors.

@a8m
Copy link
Author

a8m commented Apr 7, 2015

I'll think you get me wrong, I'm not fan of this "feature" and not use it actually.
but some people does(the amount is pointless), and since this "bug" lives outside more than two years, I prefer to catalog it as a "feature".

@silverwind
Copy link
Contributor

I have the fix for this almost ready. The only uncertainty is precedence. Should require('.') give the module in PWD or the one in NODE_PATH if both exist?

@Fishrock123
Copy link
Contributor

@silverwind Doesn't NODE_PATH essentially overwrite what would be the CWD?

@silverwind
Copy link
Contributor

@Fishrock123 no, the array of search paths is just extended and paths in NODE_PATH are put in front:

https://github.com/iojs/io.js/blob/v1.x/lib/module.js#L474

@silverwind
Copy link
Contributor

require('./') is a special case that doesn't use search paths at all. With my fix, require('.') would need to use search paths, and my current approach is to add PWD either in front or in the end of that path array.

@a8m
Copy link
Author

a8m commented Apr 7, 2015

Should require('.') give the module in PWD or the one in NODE_PATH if both exist?

NODE_PATH

@silverwind
Copy link
Contributor

NODE_PATH

Is that really needed? Does your PWD contain another module? It would complicate the fix quite a lot. The search paths used by require are

[/* NODE_PATH paths */, /* node_modules etc. */]

That array is created on startup, and I can't easily discern paths inserted by NODE_PATH from regular paths, and there is the possibilty that NODE_PATH changes during runtime. I'd much prefer just inserting PWD at position 0 if require(.) is used.

@a8m
Copy link
Author

a8m commented Apr 7, 2015

As far as I know, this shouldn't work when NODE_PATH changes during runtime.

Is that really needed? Does your PWD contain another module? It would complicate the fix quite a lot.

You can play with it yourself (by comparing >=1.6.2 against <=1.6.1). like so.

silverwind added a commit that referenced this issue Apr 16, 2015
This commit restores the functionality of adding a module's path to
NODE_PATH and requiring it with require('.'). As NODE_PATH was never
intended to be used as a pointer to a module directory (but instead, to
a directory containing directories of modules), this feature is also
being deprecated in turn, to be removed at a later point in time.

PR-URL: #1363
Fixes: #1356
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Reviewed-By: Rod Vagg <[email protected]>
@silverwind
Copy link
Contributor

Fixed by 3ad82c3. Note that this usage will print a single deprecation warning on first use, and will be removed in 3.0.0, as it stands now.

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