Skip to content
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: refactor "options" processing as a function #7165

Closed
wants to merge 1 commit into from

Conversation

thefourtheye
Copy link
Contributor

Checklist
  • tests and code linting passes
  • the commit message follows commit guidelines
Affected core subsystem(s)

fs

Description of change

As it is the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
similar functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
separate function.


cc @nodejs/fs @nodejs/collaborators

Marking this as major, as this might break some code in the wild.

@thefourtheye thefourtheye added fs Issues and PRs related to the fs subsystem / file system. semver-major PRs that contain breaking changes and should be released in the next major version. labels Jun 5, 2016
@thefourtheye
Copy link
Contributor Author

@@ -41,6 +41,25 @@ const isWindows = process.platform === 'win32';
const DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
const errnoException = util._errnoException;

function getOptions(options, defaultOptions) {
let actualType = typeof options;
Copy link
Contributor

@mscdex mscdex Jun 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW v8 still does not (IIRC) optimize storing typeof foo in a variable. It's faster to just inline the typeof without using a variable (e.g. typeof actualType === 'function').

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how I understand it too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@benjamingr
Copy link
Member

Generally +1 and LGTM, left a nit.

I think this can safely be a minor - this should only break code that parses error messages - right?

@mscdex
Copy link
Contributor

mscdex commented Jun 5, 2016

AFAIK changing error message(s) still makes it a semver-major change.

@seishun
Copy link
Contributor

seishun commented Jun 6, 2016

While we're at it, either the error should say "object that isn't a function", or functions should be accepted as option bags too.

@thefourtheye
Copy link
Contributor Author

@seishun The default options is used because, the functions which call getOptions handle the "options passed which are actually functions" case.

typeof options + ' instead.');
}

options.encoding === 'buffer' || assertEncoding(options.encoding);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please place this in an if (). no sense abusing JS's logical operators to run code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya sure... I changed it to an if block.

assert.throws(function() {
fs.createReadStream(example, 0);
}, /"options" argument must be a string or an object/);
}, /"options" must be a string or an object/);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not keep the other tests and adapt the string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@silverwind Now, I just changed the strings and allowed only null.

@silverwind
Copy link
Contributor

LGTM with question.

@thefourtheye thefourtheye force-pushed the refactor-fs-options branch 2 times, most recently from ffd1fb8 to 706316c Compare June 25, 2016 18:35
@thefourtheye
Copy link
Contributor Author

Bump!

@@ -41,6 +41,24 @@ const isWindows = process.platform === 'win32';
const DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
const errnoException = util._errnoException;

function getOptions(options, defaultOptions) {
if (options == null || typeof options === 'function') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to double check that using == null is intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, @trevnorris. It is intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes people pass null and sometimes undefined. That is why I wrote it like this. Eg: https://github.com/isaacs/node-graceful-fs/blob/master/graceful-fs.js#L89

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(a bit late, sorry)
My only beef with this is that next time a developer sees this, they may become eager to "fix" this, causing either a bug or a new discussion about this pattern. My preference is to just be explicit and check for null and undefined explicitly with ===. Just my 2 cents.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ronkorving Fair Enough. Changed it.

@trevnorris
Copy link
Contributor

One question, otherwise LGTM

@thefourtheye
Copy link
Contributor Author

Okay, added a commit to fix #7655 as well. PTAL.

if (options.encoding !== 'buffer')
assertEncoding(options.encoding);

return Object.assign(defaultOptions, options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably only do this where we need to modify it, otherwise there will be a hit to each call

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Fishrock123 You mean if we don't actually modify options, we don't want to create this copy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, that's what I am afraid of. Then the actual logic of options processing will not at the same place. Perhaps we can have a second parameter in the function which can be used to flag if a copy has to be made. What do you think?

Copy link
Contributor Author

@thefourtheye thefourtheye Jul 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Fishrock123 I changed it to util._extend from Object.assign. Hope the hit will not be that much now, at least as per #7655 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does util._extend solve this problem? By the way, Object.assign should've become quite a bit faster since V8 5.1 (see http://v8project.blogspot.jp/2016/04/v8-release-51.html). Now I do believe someone was adding a benchmark to compare the two, so I'm not making the assertion that util._extends should be avoided (yet). But a copy is a copy, and is probably more than we need in quite a few cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To think of it, it just copies things to defaultOptions. That object is constructed already in memory. Would this still be a problem?

@micnic
Copy link
Contributor

micnic commented Jul 13, 2016

LGTM
I'm just wondering if we should also fix #7655 for v4.x or not

@MylesBorins
Copy link
Contributor

@micnic how do you think it could be done in a non semver major way?

@micnic
Copy link
Contributor

micnic commented Jul 15, 2016

@thealphanerd something like options = util._extend({}, options); as the first expression in the affected methods would do the job, I don't think it is a semver major because it's an expected behavior and everywhere in the core modules except for some fs methods the external objects are not modified. In any case the impact of this change would be minimal, I could discover this only by using Object.freeze(), most of the users are using inline defined objects without reusing or freezing them.

@thefourtheye
Copy link
Contributor Author

@thefourtheye thefourtheye force-pushed the refactor-fs-options branch 3 times, most recently from 5c0feb3 to 845eeaf Compare July 22, 2016 13:00
@addaleax
Copy link
Member

@thealphanerd started a comparison CITGM run with v6.3.1 yesterday with the same vinyl-fs failures: https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/371/ (from #8253 (comment)).

That shows the same failures, so the failures here are likely unrelated…

@MylesBorins
Copy link
Contributor

/cc @phated

On Sat, Aug 27, 2016, 11:02 AM Anna Henningsen notifications@github.com
wrote:

@thealphanerd https://github.com/TheAlphaNerd started a comparison
CITGM run with v6.3.1 yesterday with the same vinyl-fs failures:
https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/371/ (from #8253
(comment)
#8253 (comment)).

That shows the same failures, so the failures here are likely unrelated…


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#7165 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAecVyWwn5yzmRmF-aUFNFUWrqXpBP_iks5qkBlSgaJpZM4IudDT
.

@thefourtheye
Copy link
Contributor Author

Squashed and Rebased.

@thefourtheye
Copy link
Contributor Author

@jasnell
Copy link
Member

jasnell commented Sep 30, 2016

CI looks good other than a known flaky failure. @thefourtheye, do you want to go ahead and get this landed?

As it is, the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
other functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
seperate function.
@thefourtheye
Copy link
Contributor Author

Landed in e8e969a. Thanks for the follow-up @jasnell :-)

thefourtheye added a commit that referenced this pull request Oct 5, 2016
As it is, the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
other functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
seperate function.

PR-URL: #7165
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Nicu Micleușanu <micnic90@gmail.com>
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@thefourtheye thefourtheye deleted the refactor-fs-options branch October 5, 2016 18:51
@addaleax
Copy link
Member

addaleax commented Oct 5, 2016

Is this only semver-major due to the changed error messages? If so, would it make sense to pull this into v7.0.0? To me the diff looks like it could likely cause conflicts when backporting to v7 otherwise…

@thefourtheye
Copy link
Contributor Author

@addaleax The encoding assertion happens for all the functions now. That also would qualify as a major change I believe.

@addaleax
Copy link
Member

addaleax commented Oct 5, 2016

Okay then, that’s a bit more than just changed messages. I’m not sure, but maybe it’s still worth to ping @nodejs/ctc and see if anybody feels strongly about it?

@Fishrock123
Copy link
Contributor

yeah, prefer major.

If you want it in v7 we should discuss this now

@jasnell
Copy link
Member

jasnell commented Oct 6, 2016

I'm ok with pulling this into v7. @nodejs/ctc ... thoughts?

@addaleax
Copy link
Member

addaleax commented Oct 6, 2016

Seems okay to me, yes. 👍

@jasnell
Copy link
Member

jasnell commented Oct 6, 2016

If there are no objections from @nodejs/ctc by Monday, I'll pull this in to v7.x-staging

@jasnell jasnell added this to the 7.0.0 milestone Oct 6, 2016
jasnell pushed a commit that referenced this pull request Oct 10, 2016
As it is, the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
other functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
seperate function.

PR-URL: #7165
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Nicu Micleușanu <micnic90@gmail.com>
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
kevinoid pushed a commit to kevinoid/fs-file-sync-fd that referenced this pull request Dec 13, 2016
As it is, the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
other functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
seperate function.

PR-URL: nodejs/node#7165
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Nicu Micleușanu <micnic90@gmail.com>
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
kevinoid pushed a commit to kevinoid/fs-file-sync-fd that referenced this pull request Dec 13, 2016
As it is, the "options" processing is repeated in all the functions
which need it. That introduces checks which are inconsistent with
other functions and produces slightly different error messages.

This patch moves the basic "options" validation and processing to a
seperate function.

PR-URL: nodejs/node#7165
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Nicu Micleușanu <micnic90@gmail.com>
Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@gibfahn gibfahn mentioned this pull request Jun 15, 2017
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.