-
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
fs: allow overring fs for streams #29083
Conversation
e7563b2
to
4846e3f
Compare
We have been moving in the opposite direction for many apis... Making them more difficult or impossible to monkey patch for both maintenance and security reasons. I'm not sure this pr is the right approach. We should revisit or strategy around this and build better hook points that are safer and supportable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making the -1 explicit until this can be discussed further
@jasnell: I get your point but I think I disagree. This is more about composition than encapsulation. We are allowing the user to pass a public API interface. For me this is no different than letting users create their on read and write streams using e.g. |
I'll fix @addaleax comments once there is consensus. |
@jasnell I don’t think it qualifies as monkey-patching if we provide a public API for overriding methods. In my opinion this is exactly the kind of approach we should take in order to avoid monkey-patching. /cc @nodejs/tsc |
I’m not convinced that there is so much code in WriteStream or ReadStream that can’t easily be duplicated in a module, if one desired so. I’m unsure if this would solve the graceful-fs problems or not. |
Right now graceful-fs creates new ES5 object constructors which create objects that extend fs.ReadStream and fs.WriteStream with an overridden open method to enable retry on ENFILE/EMFILE. Even this little change means that the overridden open method can (does) diverge from the node.js method. The native WrtieStream in node.js 5.5.0+ supports an This change would allow graceful-fs to skip re-implementing the stream open methods if run under node.js 13+, it would be able to just inject the fs option to the constructor instead. |
As opposed to overriding like this or monkeypatching, what I'd prefer to see is the improved ability for developers to create their own alternative implementations using supported lower level APIs... Something more along the lines of... class MyAlternativeWriter extends fs.FileWriteBase {
open() { /* ... */ }
close() { /* ... */ }
/* ... */
} While the differences in the approaches may be subtle, this would allow anyone inspecting the object and seeing the |
aa36717
to
752a5b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ftr, I liked the previous approach (passing an fs
object), but it doesn’t make a huge difference anyway.
I'm fine with either... |
@jasnell I don't think this is monkey-patching, it is introducing an API so that monkey-patching wouldn't be used. That API would be documented and its usage would be visible. Also, we could just forbid this call with policies or harden method later, security-wise. In general, I am in favour (if this would help to minimize monkey-patching), but I am not sure about the API yet and I don't think that |
I do agree with @jasnell that having the stream internally store references to the individual methods is best so the stream ignores any monkey-patching done after construction but I think it would be simpler for the public API to just accept a single With the fs.createReadStream(fn, {
fs: {
open: common.mustCall(fs.open),
read: common.mustCallAtLeast(fs.read, 1),
close: common.mustCall(fs.close)
}
}); |
@ronag Linter is still failing… |
How do I run the linter without having to rebuild the whole thing? |
If it's just JavaScript linting, |
(Whoever lands this should edit the commit first line for typos since those end up displayed prominently in the change log files.) |
Landed in 2b9847c. |
Notable changes: * assert: * Implement `assert.match()` and `assert.doesNotMatch()` (Ruben Bridgewater) #30929 * events: * Add `EventEmitter.on` to async iterate over events (Matteo Collina) #27994 * Allow monitoring error events (Gerhard Stoebich) #30932 * fs: * Allow overriding `fs` for streams (Robert Nagy) #29083 * perf_hooks: * Move `perf_hooks` out of experimental (legendecas) #31101 * repl: * Implement ZSH-like reverse-i-search (Ruben Bridgewater) #31006 * tls: * Add PSK (pre-shared key) support (Denys Otrishko) #23188 PR-URL: #31238
- version: REPLACEME | ||
pr-url: https://github.com/nodejs/node/pull/REPLACEME | ||
description: The `fs` options allow overriding the used `fs` | ||
implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Late nit: it would be ideal to keep the versioning order the next time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
versioning order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes entry should be at the top but it's at the bottom of the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my mistake. I though it was the other way around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no clear rule for it so far. So it's different each time and it's just good to keep it consistent in the changes itself. We might want to define an order at some point.
Notable changes: * assert: * Implement `assert.match()` and `assert.doesNotMatch()` (Ruben Bridgewater) #30929 * events: * Add `EventEmitter.on` to async iterate over events (Matteo Collina) #27994 * Allow monitoring error events (Gerhard Stoebich) #30932 * fs: * Allow overriding `fs` for streams (Robert Nagy) #29083 * perf_hooks: * Move `perf_hooks` out of experimental (legendecas) #31101 * repl: * Implement ZSH-like reverse-i-search (Ruben Bridgewater) #31006 * tls: * Add PSK (pre-shared key) support (Denys Otrishko) #23188 PR-URL: #31238
Notable changes: * assert: * Implement `assert.match()` and `assert.doesNotMatch()` (Ruben Bridgewater) #30929 * events: * Add `EventEmitter.on` to async iterate over events (Matteo Collina) #27994 * Allow monitoring error events (Gerhard Stoebich) #30932 * fs: * Allow overriding `fs` for streams (Robert Nagy) #29083 * perf_hooks: * Move `perf_hooks` out of experimental (legendecas) #31101 * repl: * Implement ZSH-like reverse-i-search (Ruben Bridgewater) #31006 * tls: * Add PSK (pre-shared key) support (Denys Otrishko) #23188 PR-URL: #31238
Allow overriding open, write, and close when using createReadStream() and createWriteStream(). PR-URL: nodejs#29083 Refs: nodejs#29050 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com>
This would allow modules such as
graceful-fs
to gracefully implement alternativefs
methods for fs streams.Would also make it possible for user land modules to implement alternative file systems (e.g. WebDAV, HTTP, SMB etc...) while re-using the existing streams implementation.
Refs: #29050
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes