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

path: iojs@1.6.0 breaks compatibility with previous versions #1215

Closed
feross opened this issue Mar 20, 2015 · 29 comments
Closed

path: iojs@1.6.0 breaks compatibility with previous versions #1215

feross opened this issue Mar 20, 2015 · 29 comments
Labels
confirmed-bug Issues with confirmed bugs. path Issues and PRs related to the path subsystem.

Comments

@feross
Copy link
Contributor

feross commented Mar 20, 2015

In iojs 1.5.1:

> path.dirname(undefined)
'.'

> path.dirname([ 'sup/dude' ])
'sup'

In iojs 1.6.0:

> path.dirname(undefined)
TypeError: Path must be a string. Received undefined
    at assertPath (path.js:8:11)
    at Object.posix.dirname (path.js:539:3)
    at repl:1:6
    at REPLServer.defaultEval (repl.js:124:27)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer.<anonymous> (repl.js:277:12)
    at emitOne (events.js:77:13)
    at REPLServer.emit (events.js:166:7)
    at REPLServer.Interface._onLine (readline.js:195:10)

> path.dirname([ 'sup/dude' ])
TypeError: Path must be a string. Received [ 'sup/dude' ]
    at assertPath (path.js:8:11)
    at Object.posix.dirname (path.js:539:3)
    at repl:1:6
    at REPLServer.defaultEval (repl.js:124:27)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer.<anonymous> (repl.js:277:12)
    at emitOne (events.js:77:13)
    at REPLServer.emit (events.js:166:7)
    at REPLServer.Interface._onLine (readline.js:195:10)

This appears to be a bug introduced by this PR: #1153.

This suddenly started causing tests in webtorrent and browserify to start failing. Here's an example.

@rvagg
Copy link
Member

rvagg commented Mar 20, 2015

/cc @cjihrig

@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

Looking.

@rvagg
Copy link
Member

rvagg commented Mar 20, 2015

workflow

This is all I can think of here, expose any API to a large enough audience and you're sure to have some of them using unexpected edge-cases as an integral part of their workflow.

I'm not convinced we should "fix" this but perhaps in-the-wild use is reason enough?

/ @iojs/tc please weigh in

@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

The case for undefined returning '.' makes some amount of sense. The array usage does not. Neither of these uses are documented or tested. How do we want to proceed?

@rvagg
Copy link
Member

rvagg commented Mar 20, 2015

I don't have a strong opinion on this and am tempted to call out those relying on edge-cases to fix bugs in their own code, but perhaps that's not very community-friendly of us and we should just be paving cowpaths!

@rvagg
Copy link
Member

rvagg commented Mar 20, 2015

Alternative here is to print a deprecation warning on anything other than strings, that might be the gentle way to proceed. I honestly can't make sense of path.dirname([ 'sup/dude' ]).

@johnsoftek
Copy link

+1 for deprecation warning

@feross
Copy link
Contributor Author

feross commented Mar 20, 2015

The array use case is weird – agreed. I have no idea how/why that was working before.

path.dirname(undefined) returning '.' makes more sense, though.

@feross
Copy link
Contributor Author

feross commented Mar 20, 2015

Ah, I figured out why the array parameter was working:

> path.dirname([ 'sup/dude', 'sup2/dude2' ])
'sup/dude,sup2'

The array was being toStringed. This was definitely a bug in webtorrent.

I still think we should consider making path.dirname(undefined) work like before.

@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

Some functions flat out break if a string isn't passed. I'm trying to identify those, and will remove the check from the others.

@brendanashworth brendanashworth added confirmed-bug Issues with confirmed bugs. path Issues and PRs related to the path subsystem. labels Mar 20, 2015
@rvagg
Copy link
Member

rvagg commented Mar 20, 2015

I'll put this in the 1.6.1 bucket if we can get it done today, is that reasonable @cjihrig?

@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

Coming in a few minutes.

@silverwind
Copy link
Contributor

I'm more in the camp of not supporting weird usage like path.dirname(undefined). This is definitely a user error which we mask by returning something.

This strongly reminds me of JS type coercion. Sometimes it's better to crash and burn, than to silently try to do the right thing™.

@monsanto
Copy link
Contributor

I agree with @silverwind. Special behavior on undefined should be kept to a minimum. Getting an error on path.dirname(obj.mispelledProperty) is more important than "well it sorta makes sense."

@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

FWIW, I agree completely. Making the APIs more restrictive cuts back on JavaScript wats. But, it is what it is.

@RnbWd
Copy link

RnbWd commented Mar 20, 2015

I also agree with @silverwind - but the behavior should remain consistent for now. Maybe add it as a discussion in the next meeting?

@feross
Copy link
Contributor Author

feross commented Mar 20, 2015

cc @substack

@domenic
Copy link
Contributor

domenic commented Mar 20, 2015

FWIW all string-accepting web APIs and built-in ES APIs to ToString on their arguments, instead of type-testing. I am surprised io.js is trying to break with that; it violates my expectations.

@feross
Copy link
Contributor Author

feross commented Mar 20, 2015

Breaking working npm packages is not cool, even if it's the right API decision for iojs.

If we're going to make an API more restrictive in the inputs it accepts, we should strive to have a deprecation notice for a while first. As Rod says, it's the gentler way to proceed and nicer to users :)

cjihrig added a commit that referenced this issue Mar 20, 2015
a465840 added strict type
checking for the methods in the path module. However, dirname(),
basename(), and extname() actually had some undocumented uses
in the wild. This commit loosens the type checking on those
methods.

Fixes: #1215
PR-URL: #1216
Reviewed-By: Rod Vagg <rod@vagg.org>
@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

Fixed in 8de78e4

@cjihrig cjihrig closed this as completed Mar 20, 2015
@cjihrig
Copy link
Contributor

cjihrig commented Mar 20, 2015

Let me know if you're still having problems.

@feross
Copy link
Contributor Author

feross commented Mar 20, 2015

Thanks!

feross added a commit to webtorrent/create-torrent that referenced this issue Mar 20, 2015
@xaka
Copy link

xaka commented Mar 20, 2015

What you're saying is right, it's just it doesn't apply to this situation
IMHO. Have you ever seen language APIs coercing NULLs and VOIDs to
different types with different values? I personally haven't and would
consider it as an awful side effect. Such things cost a lot of money due to
longer debugging time. I think having a warning is the best (and must have)
option here, and it should go away in next releases.

On Thu, Mar 19, 2015 at 6:04 PM, Domenic Denicola notifications@github.com
wrote:

FWIW all string-accepting web APIs and built-in ES APIs to ToString on
their arguments, instead of type-testing. I am surprised io.js is trying to
break with that; it violates my expectations.


Reply to this email directly or view it on GitHub
#1215 (comment).

@domenic
Copy link
Contributor

domenic commented Mar 20, 2015

I have seen such a language, it's called JavaScript. It's very nice and much code depends on it.

@silverwind
Copy link
Contributor

We still ❤️ Brendan for this lovely coercion feature.

@stelcheck
Copy link

Just a wild thought, but why not turn a bug into a feature?

var folder = 'abc'
path.dirname(['some', folder, 'path'])
// some/abc/path

The currently reported case would remain valid, and array with more than one value would now also work. Thoughts? Stupid or a good idea?

@RnbWd
Copy link

RnbWd commented Mar 20, 2015

@domenic and @feross make good points - breaking compatibility with existing modules should only happen in extreme cases. However, using path.dirname(undefined) makes no sense and is probably a programming error. I see no harm in warning people about it (without any intention of changing the API).

@rauchg
Copy link
Contributor

rauchg commented Mar 20, 2015

iojs shouldn't break existing code this easily.

It'd be better to provide type annotations to avoid such usage at compile time (eg: Flow, TypeScript) moving forward. This is also a more elegant way to trigger warnings of deprecation than console.warns (which can introduce subtle breakage by making hot codepaths slow).

And of course, most importantly, it wouldn't break existing code.

@aredridel
Copy link
Contributor

krakenjs/localizr was broken by this too, surprisingly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. path Issues and PRs related to the path subsystem.
Projects
None yet
Development

No branches or pull requests