-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
feat: make fs.read params optional #31402
feat: make fs.read params optional #31402
Conversation
This makes all the parameters of the `fs.read` function, except for `fd` and the callback(when not using as a promise) optional. They will default to sensible defaults fixes nodejs#31237
I don't think it's that easy, especially since there are 3 consecutive integer parameters and trying to determine which was specified if there were less than 3 integers passed is impossible. I think we'd only be able to (reliably) support the following cases: fs.read(fd, buffer, offset, length, position, callback);
fs.read(fd, buffer, callback);
fs.read(fd, callback); For the last signature, the documentation must be updated to clearly indicate the default Additionally, I think the language features used here may cause performance issues so it'd be better to just stick to the traditional type checking. |
I see what you are saying, but i think the assumption is(and maybe it is just my assumption), that when you want to specify, for example length, that you would also need to specify any params before it. So we should know what param is being passed in since they are positional So in that case the signatures would look like this:
at least that is how i read the usage from the fs.write method that i thought was doing something similar: If that is not the case, i'm happy to amend this to just do the signatures from the above post
Which features? spread? performance isn't really in my wheel house, so i don't mind updating if that is the best way to go |
Spread in the parameter list may be ok, but last I checked destructuring and such caused performance regressions. |
Might have been fixed in V8 7.8 (#30109). |
I'm sort of drawing a blank on what other test should be added here. The only one I can think of, that wouldn't be duplicating something from an already existing test, is testing that the default buffer that is created is the correct size. I've added that one in the latest commit |
doc/api/fs.md
Outdated
@@ -2716,10 +2716,14 @@ Returns an integer representing the file descriptor. | |||
For detailed information, see the documentation of the asynchronous version of | |||
this API: [`fs.open()`][]. | |||
|
|||
## `fs.read(fd, buffer, offset, length, position, callback)` | |||
## `fs.read(fd, [buffer[, [offset[, length[, position]]]], callback)` |
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.
As much as I dislike polymorphic signatures, I'd much prefer the approach of moving to an options
object as an alternative here. That is:
fs.read(fd, { offset: n, position: n }, callback)
It accomplishes the same goal with a much cleaner API and implementation, without the ambiguity of which argument was meant to be passed in.
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.
@jasnell I think i see what you are saying. Just for my own clarification, we keep the current signature of fs.read(fd, buffer, offset, lenght, position, callback)
, but then add another signature of fs.read(fd, options, callback)
where the options
is the buffer, offset, length, position params
So then if a user only wanted to specify some of the params, they would have to use the "options" object signature.
Does that sound correct?
One thing that jumps out at me here, is when checking to see if that second parameter is the options object instead of the buffer object, i don't think we can use typeof
since both would return object
. Or am i overthinking this?
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.
@jasnell Something else that i thought of was that the fs.write
method is similar, in that it allows for optional parameters to be passed without the use of an options object.
Perhaps we don't go the options object route? Or if we do, maybe that function and others(not sure if there are)should be updated also?
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.
I think moving that direction is ideal but doesn't have to be done all at once
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.
@jasnell @ronag does what i said here, #31402 (comment) makes sense?
For API symmetry, this should be done also on |
Yea, definitely. I'll probably send this in a second PR just to keep things clean |
I just realized that these are just doc updates, so nvm, i can add to this pr 🤦♂️ |
Benchmark results:
|
@jasnell @ronag just a friendly ping, i think my last comment may have gotten lost in the shuffle but does what i said here, #31402 (comment) make sense? |
Hey sorry, I missed the earlier notification. I'd really prefer if the changes to fs.promise were in a separate commit in the same PR. Those apis should remain consistent and having it in a separate pr could make things more difficult |
Yea, i realized after i wrote that, it was just doc updates. I guess my main question was about my thought process here:
|
Ah, right... yes, that's exactly what I'm suggesting. It gives significantly more flexibility in how those various other properties are handled. |
now using the options object instead of making all things optional
I've added a new commit that adds the signature |
Co-Authored-By: Richard Lau <riclau@uk.ibm.com>
Co-Authored-By: Richard Lau <riclau@uk.ibm.com>
I added the optional options um...... option, so |
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.
I think
test-fs-read-optional-options-params.js
test/parallel/test-fs-read-optional-params.js
can be just one file
Yea, probably. when i was writing those, i had them in the same file, but i was having an issue because i was re-using the same file. i'll try to rework it to make it work |
@ronag I added another test and combined the 2 tests files into 1 |
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.
LGTM
Landed in b6da55f |
* `buffer` {Buffer|Uint8Array} **Default:** `Buffer.alloc(16384)` | ||
* `offset` {integer} **Default:** `0` | ||
* `length` {integer} **Default:** `buffer.length` | ||
* `position` {integer} **Default:** `null` |
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.
This is not the same as the actual. options.position
is the undefined
when default
* `buffer` {Buffer|TypedArray|DataView} **Default:** `Buffer.alloc(16384)` | ||
* `offset` {integer} **Default:** `0` | ||
* `length` {integer} **Default:** `buffer.length` | ||
* `position` {integer} **Default:** `null` |
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.
same here
This makes all the parameters of the `fs.read` function, except for `fd` and the callback(when not using as a promise) optional. They will default to sensible defaults. Fixes: nodejs#31237 PR-URL: nodejs#31402 Reviewed-By: Robert Nagy <ronagy@icloud.com>
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesThis makes all the parameters of the
fs.read
function, exceptfor
fd
and the callback(when not using as a promise) optional.fixes #31237
I still need to add a few tests(i've done some manual testing), but wanted to get this out to start the discussion.
There is one part, which i've commented in the code, where i did something to satisfy the linting, but i wasn't thrilled with it. Maybe having a lint exception here might be better? Looking for input on that
I'm not a typescript user, but i wonder if changing the function signature will somehow have a negative effect