-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
iojs: introduce internal modules #848
Conversation
Does this actually help? Crazy people will just require('internal/freelist') in their code. |
that's the idea, they can't. |
Ah, I see now. I'm not sure if it's worth introducing such a framework for just one module which might get removed. |
It is not just for one module. The idea is to move there everything non-public bit by bit. |
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. |
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. |
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. |
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. |
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 |
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. |
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. |
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 |
-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. |
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 |
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. |
For the sake of the functionality (regardless of my stance), why not just block i.e.: > require('_http_common');
TypeError: cannot require private module
at repl:1:7
... |
+1 for underscore in favor of |
@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. |
We should also consider, as best we can, the long term effects with ES6 modules. |
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. |
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. |
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. |
@yursha because being able to require parts of a library or a module is super useful and a lot of packages use that ability. |
They are already implemented differently. There are many reasons for that, both historical and practical. |
@yursha Also a problem, but much harder to solve. If we prohibit |
@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. |
@yursha Like @benjamingr said. It is super useful. For an example, look at lodash. |
Useful for browserify. Otherwise |
@yursha browserify includes only files that are explicitly |
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
|
I don't really understand how it could cause that, but the parent commit works fine, and this ones throws like crazy. |
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. |
Looks like gyp passes paths to js2c.py differently on windows |
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