Skip to content

Conversation

@dfabulich
Copy link
Contributor

@dfabulichdfabulich commented May 30, 2017

Consider this sample code.

constfs=require('fs');const{promisify}=require('util');constexists=promisify(fs.exists);exists(__filename).then(x=>console.log(x)).catch(err=>console.error("oh no",err));

Expected: The code should log true, because the current file exists.
Actual: It logs oh no true, as the promise is rejected with err set to true

This is happening because fs.exists does not follow the standard format of taking an error-first callback as the last argument. Luckily, util.promisify provides a .custom feature for promisifying callbacks that don't follow the nodeback style.

In this PR, we provide a custom promise implementation for fs.exists.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

fs

@nodejs-github-botnodejs-github-bot added the fs Issues and PRs related to the fs subsystem / file system. label May 30, 2017
Copy link
Member

Choose a reason for hiding this comment

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

I’d recommend wrapping these in {}, too (even if it’s just a single line), and the callback should probably be wrapped in common.mustCall()

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

done

lib/fs.js Outdated
Copy link
Member

Choose a reason for hiding this comment

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

You could just use resolve instead of (x) => resolve(x), if you like

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

done

@addaleaxaddaleax added promises Issues and PRs related to ECMAScript promises. semver-minor PRs that contain new features and should be released in the next minor version. labels May 30, 2017
@dfabulichdfabulichforce-pushed the dgf-exists-promisify branch from 092634c to e3d3f3eCompareMay 30, 2017 21:52
Copy link
Contributor

@refackrefack left a comment

Choose a reason for hiding this comment

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

LGTM % 2 nits

Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO it's more important to assert:
assert.strictEqual(typeof x, 'boolean')

Copy link
Member

Choose a reason for hiding this comment

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

In that case you might just strictEqual(x, true) ;)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

done, assert.strictEqual(x, true);

lib/fs.js Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

very small nit: place the enumerable: false before the value

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

meh, done

Copy link
Contributor

Choose a reason for hiding this comment

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

🤷‍♂️ it's a style preference.
Thank you for indulging me 🎩

@dfabulichdfabulichforce-pushed the dgf-exists-promisify branch from e3d3f3e to 171a9aaCompareMay 30, 2017 22:17
lib/fs.js Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't the whole point of promisify NOT to use new Promise?

Copy link
Member

Choose a reason for hiding this comment

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

No, the point of promisify is to give users a standard interface for turning Node-style callbacks into functions that return Promises. And since this is a deprecated API, I don’t think there’s a need to micro-optimize.

Copy link
ContributorAuthor

@dfabulichdfabulichMay 30, 2017

Choose a reason for hiding this comment

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

meh, done. It's now fully micro-optimized 😉

@dfabulichdfabulichforce-pushed the dgf-exists-promisify branch from 171a9aa to 8d93e74CompareMay 30, 2017 23:12
lib/fs.js Outdated

Choose a reason for hiding this comment

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

All values in defineProperty default to false, so this may not be necessary?

Alternatively, is it intentional that it is not configurable or writable? (I assume at least the latter is true)

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK it's supposed to be "hidden" from userland.
See lib/fs.js#L780

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Indeed, I was copying and pasting from line 780, because I incorrectly assumed that enumerable: false was required to conceal it from userland.

MDN says the defaults are:

{enumerable: false, configurable: false, writeable: false}

Those look like good defaults to me. I'll remove enumerable: false here and use the defaults. (I guess we should remove it at line 780, but I'll let somebody else do that.)

Copy link
Member

Choose a reason for hiding this comment

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

I like being explicit in code, especially if it helps clarify intent and when the defaults are not obvious to casual readers, which is why I added the enumerable: false; but I won’t force that on you if you don’t like it.

(@dfabulich Thanks for being so quick with updating here, but just so there’s no confusion: Our opinions aren’t inherently better than yours, and if you think a collaborator makes a request that you don’t agree with, you should feel free to say so.)

Copy link
ContributorAuthor

@dfabulichdfabulichMay 31, 2017

Choose a reason for hiding this comment

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

I think all of the proposed changes here have been (small) improvements or no difference to me. I aim to please. :-)

I do think it's about ready to land now.

@dfabulichdfabulichforce-pushed the dgf-exists-promisify branch from 8d93e74 to 15f3f0bCompareMay 31, 2017 16:52
@jasnell
Copy link
Member

jasnell pushed a commit that referenced this pull request Jun 1, 2017
PR-URL: #13316 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Vladimir Kurchatkin <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Timothy Gu <[email protected]>
@vsemozhetbyt
Copy link
Contributor

It seems this can be closed now with 65531d0 ?

@jasnell
Copy link
Member

Yes, was just getting to that ;-) ... Landed in 65531d0

@jasnelljasnell closed this Jun 1, 2017
jasnell pushed a commit that referenced this pull request Jun 5, 2017
PR-URL: #13316 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Vladimir Kurchatkin <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Timothy Gu <[email protected]>
@jasnelljasnell mentioned this pull request Jun 5, 2017
jasnell added a commit to jasnell/node that referenced this pull request Jun 7, 2017
* **Async Hooks** * When one `Promise` leads to the creation of a new `Promise`, the parent `Promise` will be identified as the trigger [[`135f4e6643`](nodejs@135f4e6643)] [nodejs#13367](nodejs#13367). * **Dependencies** * libuv has been updated to 1.12.0 [[`968596ec77`](nodejs@968596ec77)] [nodejs#13306](nodejs#13306). * npm has been updated to 5.0.3 [[`ffa7debd7a`](nodejs@ffa7debd7a)] [nodejs#13487](nodejs#13487). * **File system** * The `fs.exists()` function now works correctly with `util.promisify()` [[`6e0eccd7a1`](nodejs@6e0eccd7a1)] [nodejs#13316](nodejs#13316). * fs.Stats times are now also available as numbers [[`c756efb25a`](nodejs@c756efb25a)] [nodejs#13173](nodejs#13173). * **Inspector** * It is now possible to bind to a random port using `--inspect=0` [[`cc6ec2fb27`](nodejs@cc6ec2fb27)] [nodejs#5025](nodejs#5025). * **Zlib** * A regression in the Zlib module that made it impossible to properly subclasses `zlib.Deflate` and other Zlib classes has been fixed. [[`6aeb555cc4`](nodejs@6aeb555cc4)] [nodejs#13374](nodejs#13374).
rvagg pushed a commit that referenced this pull request Jun 8, 2017
* **Async Hooks** * When one `Promise` leads to the creation of a new `Promise`, the parent `Promise` will be identified as the trigger [[`135f4e6643`](135f4e6643)] [#13367](#13367). * **Dependencies** * libuv has been updated to 1.12.0 [[`968596ec77`](968596ec77)] [#13306](#13306). * npm has been updated to 5.0.3 [[`ffa7debd7a`](ffa7debd7a)] [#13487](#13487). * **File system** * The `fs.exists()` function now works correctly with `util.promisify()` [[`6e0eccd7a1`](6e0eccd7a1)] [#13316](#13316). * fs.Stats times are now also available as numbers [[`c756efb25a`](c756efb25a)] [#13173](#13173). * **Inspector** * It is now possible to bind to a random port using `--inspect=0` [[`cc6ec2fb27`](cc6ec2fb27)] [#5025](#5025). * **Zlib** * A regression in the Zlib module that made it impossible to properly subclasses `zlib.Deflate` and other Zlib classes has been fixed. [[`6aeb555cc4`](6aeb555cc4)] [#13374](#13374).
rvagg pushed a commit that referenced this pull request Jun 8, 2017
* **Async Hooks** * When one `Promise` leads to the creation of a new `Promise`, the parent `Promise` will be identified as the trigger [[`135f4e6643`](135f4e6643)] [#13367](#13367). * **Dependencies** * libuv has been updated to 1.12.0 [[`968596ec77`](968596ec77)] [#13306](#13306). * npm has been updated to 5.0.3 [[`ffa7debd7a`](ffa7debd7a)] [#13487](#13487). * **File system** * The `fs.exists()` function now works correctly with `util.promisify()` [[`6e0eccd7a1`](6e0eccd7a1)] [#13316](#13316). * fs.Stats times are now also available as numbers [[`c756efb25a`](c756efb25a)] [#13173](#13173). * **Inspector** * It is now possible to bind to a random port using `--inspect=0` [[`cc6ec2fb27`](cc6ec2fb27)] [#5025](#5025). * **Zlib** * A regression in the Zlib module that made it impossible to properly subclasses `zlib.Deflate` and other Zlib classes has been fixed. [[`6aeb555cc4`](6aeb555cc4)] [#13374](#13374).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fsIssues and PRs related to the fs subsystem / file system.promisesIssues and PRs related to ECMAScript promises.semver-minorPRs that contain new features and should be released in the next minor version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

11 participants

@dfabulich@jasnell@vsemozhetbyt@Jessidhia@refack@addaleax@lpinca@TimothyGu@vkurchatkin@MylesBorins@nodejs-github-bot