-
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
fs: remove maybeCallback function #7168
Conversation
Generally I like this change but I'm not really sure it's worth it given the amount of breakage it might cause in the wild. ---I tried running a smoke test but the CI gets frozen "Loading" when I attempt it - but I definitely think it's worth running in this case--- Smoke test: https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/294/ Code changes themselves LGTM. |
I think the potential for ecosystem fallout is a bit too high to justify. Note that You could change |
If we're going to break stuff, I'd rather break it to throw immediately when no callback is passed. Instead of throwing sometime in the future when the stack has been lost. |
@thealphanerd I looked at the smoke test output - it's green but looks like there are errors in the console output - can you PTAL? |
some of our production code would break with this change... get ready to cringe: that's because with a preflight stat verifying path or read/writability, it turns out fs read/writes done in the fire-and-forget fashion (never passing a callback) are not only fine but also reliable |
@reqshark wait, what?? |
While not passing a callback might be equal to passing Occasionally program errors should be ignored, and the ability to not have to write an error handler for an inconsequential routine will reduce lines of code... for example, writing a The decision not to pass the callback should result in an immediate consequence, either throw immediately or its |
If we are going to make a semver-major change here can we please simply throw immediately? Throwing in the future is one of the dumbest designs in node today. |
@@ -1 +1 @@ | |||
require('fs').readFile('/'); // throws EISDIR | |||
require('fs').readFile('/', undefined); // throws EISDIR |
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.
Should it not throw with arguments.length being 1?
+1 to throwing immediately. Thinking out loud: I do get the case where an explicit noop would be useful, however. I'm wondering if some form of sentinel value could be used to explicitly signal that the async method should simply not bother attempting to callback tho. A Symbol would work... fs.writeFile('/tmp/foo', 'hello there', fs.NoCallback); I dunno, just a thought. |
@jasnell Seems like a better option for a userland module to do? |
71adf44
to
2c32c1f
Compare
Okay, updated the PR to throw if the callback is not passed. PTAL. |
Sweet. The code change LGTM. Looks like we're missing test coverage checking if all the altered functions throw. Mind making sure there's a single check for each method to make sure it throws if no callback is passed? |
2c32c1f
to
bc57b2f
Compare
@trevnorris I included a test now to check if the functions fail when callback is not passed. |
@@ -221,19 +191,17 @@ fs.Stats.prototype.isSocket = function() { | |||
}); | |||
|
|||
fs.access = function(path, mode, callback) { | |||
callback = makeCallback(arguments[arguments.length - 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.
hmm... not thrilled about this approach. For instance, the following is technically not an incorrect way of calling the fs.access()
function even if the extraneous arguments on the end aren't supported. This code, however, would fail:
fs.access('/some/path', () => {}, 'useless', 'arguments', 'here');
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 Perhaps I can traverse the arguments
backwards and see if there is atleast one function object passed?
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.
It's a little verbose, but should be as simple as:
if (typeof mode === 'function') {
callback = mode;
mode = fs.F_OK;
}
if (typeof mode !== 'number' || Number.isNaN(mode)) {
throw new TypeError('mode must be a number');
}
if (typeof callback !== 'function') {
throw new TypeError('callback must be a function');
}
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.
If we are doing this, we should probably do the same for other methods as well.
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.
okay. I'd like that change, but let's keep that for another PR.
I agree with @jasnell's opinion on grabbing the last argument. Other than that LGTM. |
Still LGTM. With the note above that changing how arguments are parsed should go into another PR. |
The "fs" module has two functions called `maybeCallback` and `makeCallback`, as of now. The `maybeCallback` creates a default function to report errors, if the parameter passed is not a function object. Basically, if the callback is omitted in some cases, this function is used to create a default callback function. The `makeCallback`, OTOH, creates a default function only if the parameter passed is `undefined`, and if it is not a function object it will throw an `Error`. This patch removes the `maybeCallback` function and makes the callback function argument mandatory for all the async functions.
bc57b2f
to
bff78cd
Compare
Rebased. CI Run: https://ci.nodejs.org/job/node-test-pull-request/3366/ |
Landed in 9359de9. |
The "fs" module has two functions called `maybeCallback` and `makeCallback`, as of now. The `maybeCallback` creates a default function to report errors, if the parameter passed is not a function object. Basically, if the callback is omitted in some cases, this function is used to create a default callback function. The `makeCallback`, OTOH, creates a default function only if the parameter passed is `undefined`, and if it is not a function object it will throw an `Error`. This patch removes the `maybeCallback` function and makes the callback function argument mandatory for all the async functions. PR-URL: #7168 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
oh hey all... looks like this broke /cc @nodejs/npm |
This reverts commit 9359de9. Original Commit Message: The "fs" module has two functions called `maybeCallback` and `makeCallback`, as of now. The `maybeCallback` creates a default function to report errors, if the parameter passed is not a function object. Basically, if the callback is omitted in some cases, this function is used to create a default callback function. The `makeCallback`, OTOH, creates a default function only if the parameter passed is `undefined`, and if it is not a function object it will throw an `Error`. This patch removes the `maybeCallback` function and makes the callback function argument mandatory for all the async functions. PR-URL: nodejs#7168 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Indeed, see npm/npm#13457 for further breakage that this causes in npm. What's the status on this? |
Status is that we will be reverting this specific change and taking a On Wednesday, July 27, 2016, Forrest L Norvell notifications@github.com
|
This reverts commit 9359de9. Original Commit Message: The "fs" module has two functions called `maybeCallback` and `makeCallback`, as of now. The `maybeCallback` creates a default function to report errors, if the parameter passed is not a function object. Basically, if the callback is omitted in some cases, this function is used to create a default callback function. The `makeCallback`, OTOH, creates a default function only if the parameter passed is `undefined`, and if it is not a function object it will throw an `Error`. This patch removes the `maybeCallback` function and makes the callback function argument mandatory for all the async functions. PR-URL: nodejs#7168 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This reverts commit 9359de9. Original Commit Message: The "fs" module has two functions called `maybeCallback` and `makeCallback`, as of now. The `maybeCallback` creates a default function to report errors, if the parameter passed is not a function object. Basically, if the callback is omitted in some cases, this function is used to create a default callback function. The `makeCallback`, OTOH, creates a default function only if the parameter passed is `undefined`, and if it is not a function object it will throw an `Error`. This patch removes the `maybeCallback` function and makes the callback function argument mandatory for all the async functions. PR-URL: #7168 Reviewed-By: Trevor Norris <trev.norris@gmail.com> PR-URL: #7846 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Checklist
Affected core subsystem(s)
fs
Description of change
The "fs" module has two functions called
maybeCallback
andmakeCallback
, as of now.The
maybeCallback
creates a default function to report errors, if theparameter passed is not a function object. Basically, if the callback
is omitted in some cases, this function is used to create a default
callback function.
The
makeCallback
, OTOH, creates a default function only if theparameter passed is
undefined
, and if it is not a function object itwill throw an
Error
.This patch removes the
maybeCallback
function and makes the callbackfunction argument mandatory for all the async versions.
cc @nodejs/collaborators