Uh oh!
There was an error while loading. Please reload this page.
iojs: introduce internal modules - #848
Conversation
seishun
commented
Feb 14, 2015
Does this actually help? Crazy people will just require('internal/freelist') in their code. |
vkurchatkin
commented
Feb 14, 2015
that's the idea, they can't. |
seishun
commented
Feb 14, 2015
Ah, I see now. I'm not sure if it's worth introducing such a framework for just one module which might get removed. |
vkurchatkin
commented
Feb 14, 2015
It is not just for one module. The idea is to move there everything non-public bit by bit. |
thlorenz
commented
Feb 15, 2015
tl;dr if you use undocumented modules you run the risk of your code breaking, no need for us to fix anything here. Not a big fan of this feature. As an example inside readline-vim I depend on Same is true for any modules only to be used internally. If you wanna use them, fine but just know the risk. But if you start trying to encapsulate those you'd then also have to encapsulate the From my experience in other OO environments I've come to the conclusion that encapsulation is overrated. Just let the users make the right decisions. Marking things private explicitly or implicitly (by not documenting them) should suffice. |
brendanashworth
commented
Feb 15, 2015
I'm unsure about this change. Yes, developers using private modules causes hesitancy when putting breaking changes into the source and not bumping semver-major, but we have to draw the line somewhere - and I think that should be whether or not it is documented. The programmer should know what they are doing, and if they know what they are doing and want to require a private module, we shouldn't restrict them from doing that. |
vkurchatkin
commented
Feb 15, 2015
What you are saying is absolutely right, but also purely theoretical. When time comes to remove something that was never documented we still HAVE TO evaluate the risks of removing to it. This is the burden I want to get rid of.
You know the risk, someone doesn't. Someone who requires you module doesn't. Removing this method can potentially break thousands of modules and the only person who knew the risk was you.
Not HAVE TO. But this would be good too, eventually.
This is exactly that, marking modules as private very explicitly. |
thlorenz
commented
Feb 15, 2015
Not sure if it was clear, but I meant to stress implicitly (by not documenting them) should suffice above, meaning that no further action beyond not documenting is needed.
When I wrote that code I wasn't involved with node myself, but knew as a developer that undocumented features and/or functions marked Most devs are aware of this as I was and if not they'll have to learn the hard way unfortunately. However jumping through hoops just to somehow disable devs not to follow these conventions is over the top IMHO. |
vkurchatkin
commented
Feb 15, 2015
While you are right (as I have already said), what you say is unrealistic and unreasonable. Let's say It's so easy to discover something not documented using REPL. I understand your stance, but you give no cons. Here are the pros (from my point of view):
Some references: https://github.com/search?l=javascript&q=util._extend&ref=searchresults&type=Code&utf8=%E2%9C%93 |
meandmycode
commented
Feb 16, 2015
I'd agree that it's io.js / node that pay for other developers risks. Especially with how graph like dependencies are in node it's easy for one person's risk to affect hundreds without them realizing. In other languages it's a lot harder to shoot yourself in the foot (.NET for example requires you write reflection code and a level of execution permission that people don't assume). This will always be a balance but if one of io.js goals is agility then it seems to fit. |
thlorenz
commented
Feb 16, 2015
I agree that the convention WRT But let's get the discussion back on track to what this PR is about. Internal modules to prevent users from doing things that may cause problems for them would be nice and if they came at no cost I'd be all for it. However the price to pay for this (added complexity in the code base and possible confusion about what's going on for people trying to grok the code base) is just not worth it IMO. |
tellnes
commented
Feb 16, 2015
I'm generally in line with @thlorenz points in this thread. But if we should implement something like this, I don't think creating a magic |
seishun
commented
Feb 16, 2015
-1 for reasons already outlined by @thlorenz and also because it doesn't solve the problem completely anyway. There are still undocumented object properties and undocumented exports on otherwise public modules. |
Qard
commented
Feb 16, 2015
Indeed. Nice try, but only a partial fix. Also, I would've gone the route of freelist being in a node_modules folder only resolvable from other core files, so it could just work like any other module dependency not being accessible without doing |
chrisdickinson
commented
Feb 16, 2015
I don't have time at the moment to fully write this up at the moment, but I actually would like to have this ability in core. |
brendanashworth
commented
Feb 16, 2015
For the sake of the functionality (regardless of my stance), why not just block i.e.: >require('_http_common');
TypeError: cannotrequireprivatemoduleatrepl:1:7... |
tellnes
commented
Feb 17, 2015
+1 for underscore in favor of |
vkurchatkin
commented
Feb 17, 2015
@brendanashworth that would be an immediate breaking change. The idea is to leave underscored files and add deprecation notice to them until 2.0.0. Also a part of the PR is enabling subfolders in `lib/', which is also nice to have.
@seishun They are on my radar too, but this is a first essential step. If we want to move private stuff, we need a place where to move it first. |
trevnorris
commented
Feb 18, 2015
We should also consider, as best we can, the long term effects with ES6 modules. |
chrisdickinson
commented
Feb 21, 2015
This is a great example of a place where I'd love to be able to have modules private to io.js – it would be great to have an internal module that allowed io.js internals to place "high priority" event listeners, vs. reaching into other object state. |
benjamingr
commented
Feb 26, 2015
When I started reading it sounded like a bad idea but I think @vkurchatkin makes some really good arguments in favour encapsulation here. In many languages it's possible to use modules internally but not expose them to the outside. This isn't only a problem in core, it would also be a nice ability in userland to signal that a specific file from a module should not be included directly. Popular userland libraries share the issue. Something like a:
Which would mean this file should not be included from the outside - only from within the module or core. It's not a well thought out idea but I hope it gets the point across. I also think that @trevnorris's comments about ES6 modules are really important - any change here can have an impact on ES6 modules that don't do this sort of thing. |
brendanashworth
commented
Mar 1, 2015
How so? I think it all could be done the same way - issuing a deprecation notice when they are require'd via the module code. It could then be changed to throw an error on 2.0.0. The change for enabled subfolders could also be separated into a new commit. |
benjamingr
commented
Mar 1, 2015
@yursha because being able to require parts of a library or a module is super useful and a lot of packages use that ability. |
vkurchatkin
commented
Mar 1, 2015
They are already implemented differently. There are many reasons for that, both historical and practical. |
vkurchatkin
commented
Mar 1, 2015
@yursha Also a problem, but much harder to solve. If we prohibit |
tellnes
commented
Mar 1, 2015
@yursha Internal and userland modules are a different story. Your feature request to support this for userland modules is a real one, but out of scope for this pull request. If you can come up with a good and clean way which make it possible to require parts of a module like it works today and at the same time lets you define some files as unrequireable, then you maybe have a solution. |
tellnes
commented
Mar 1, 2015
@yursha Like @benjamingr said. It is super useful. For an example, look at lodash. |
vkurchatkin
commented
Mar 1, 2015
Useful for browserify. Otherwise |
vkurchatkin
commented
Mar 1, 2015
@yursha browserify includes only files that are explicitly |
Fishrock123
commented
Mar 26, 2015
This commit causes the entire windows test suite to fail due to some config loading issue: https://jenkins-iojs.nodesource.com/view/iojs/job/iojs+any-pr+multi/381/nodes=iojs-win2008r2/console |
Fishrock123
commented
Mar 26, 2015
I don't really understand how it could cause that, but the parent commit works fine, and this ones throws like crazy. |
bnoordhuis
commented
Mar 26, 2015
I'll look into it. I think I know what's causing it and I guess I'm partially to blame for lgtm'ing without pointing out the CI failures. |
vkurchatkin
commented
Mar 26, 2015
Looks like gyp passes paths to js2c.py differently on windows |
bnoordhuis
commented
Mar 27, 2015
FTR: #1281 |
Notable changes: * fs: corruption can be caused by fs.writeFileSync() and append-mode fs.writeFile() and fs.writeFileSync() under certain circumstances, reported in #1058, fixed in #1063 (Olov Lassus). * iojs: an "internal modules" API has been introduced to allow core code to share JavaScript modules internally only without having to expose them as a public API, this feature is for core-only #848 (Vladimir Kurchatkin). * timers: two minor problems with timers have been fixed: - Timer#close() is now properly idempotent #1288 (Petka Antonov). - setTimeout() will only run the callback once now after an unref() during the callback #1231 (Roman Reiss). * Windows: a "delay-load hook" has been added for compiled add-ons on Windows that should alleviate some of the problems that Windows users may be experiencing with add-ons in io.js #1251 (Bert Belder). * V8: minor bug-fix upgrade for V8 to 4.1.0.27. * npm: upgrade npm to 2.7.4. See npm CHANGELOG.md for details.
Internal modules can be used to share private code between public modules without risk to expose private APIs to the user.
Later some flag (build time or runtime) could be added for making unit-testing possible.
#569
R=@iojs/owners @iojs/collaborators