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
Return undefined as pkg for core modules #56
Conversation
@@ -46,7 +46,7 @@ module.exports = function resolve (x, opts, cb) { | |||
else loadNodeModules(x, y, function (err, n, pkg) { | |||
if (err) cb(err) | |||
else if (n) cb(null, n, pkg) | |||
else if (core[x]) return cb(null, x); | |||
else if (core[x]) return cb(null, x, 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 switching it from calling with undefined
to calling with null
- I'm not sure why this is an improvement?
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.
const co = require('co')
const thunkify = require('thunkify')
const resolve = thunkify(require('resolve'))
function* gen(modulePath) {
const [filePath, pkg] = yield resolve(modulePath, {})
return [filePath, pkg]
}
co(function *(){
console.log('resolved:', yield gen('path'))
}).catch((err) =>{
console.error(err.stack);
})
// unpatched:
// => resolved: [ 'p', 'a' ]
// patched:
// => resolved: [ 'path', 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.
ok so I'm trying to unpack that code sample - it seems like gen
could simply be function* gen(modulePath) { return (yield resolve(modulePath, {})).slice(0, 2); }
so if the callback is called with x, null
versus called with x, undefined
, those should be equivalent. I guess I'm not seeing where the 'a'
is coming from when unpatched.
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.
Hello, the problem is a rare case of libraries combination.
When multiple values are returned from a thunkified function that is run inside "co", the result is an array. See https://github.com/tj/co/blob/master/index.js#L139
Maybe it should always return an array, but it's about convenience vs. consistency.
On the other side "resolve", as a lower level lib, could handle problems like this, by always returning the same number of values.
Also your "slice(0, 2)" version inside the generator function, is not equivalent for the "unpatched" version. The first one does array destructuring, so it expects the sourced result to be an array and returns an array. The second one has the same behavior only for an array result, but for single value results it returns a string.
const [filePath, pkg] = yield resolve('path')
return [filePath, pkg] //=> ['p', 'a']
// vs.
return (yield resolve('path')).slice(0, 2) //=> 'pa'
In the "patched" version we get [ 'path', null ]
from both.
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 - I'm not super comfortable about working around what is definitely a bug - for convenience or no - in co
.
This also is a breaking change for anyone who's currently testing === undefined
or similar.
What about now :-) |
we get [ 'path', undefined ] with the explicit |
I know that I'm being a bit pedantic, but while this is better, now someone relying on I really think this is a bug that needs fixing in |
No problem, but there is no error case here to catch with |
who does this? you always write |
If it's possible to observe the breaking change, then it's a breaking change, even if nobody really does it. You might use arguments.length to determine if you should require the 3rd arg or not, for example. It's more explicit than checking for undefined or falsiness. |
I think that in the case of the 3rd "package" argument, either you are interested to read it or not and you want to get it in a convenient way. I cannot disagree about the extremely rare breaking usage though. |
fyi mpal9000 - I use arguments.length to validate input all the time. Like ljharb mentions, it guarantees whether the developer passed an argument as opposed to checking whether they accidentally passed in an undefined variable. Mostly this distinction helps with friendly error messages such as "method requires exactly two arguments" vs "the second argument must be a sting". In fact, that distinction is one of the reasons I may choose to use |
I'm going to close this; passing nothing is strictly better than passing This is a flaw in |
Hello, thanks for everything you share! This pull request is about a small issue that I have when combining "resolve" with "thunkify" and generators.