nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
105.53k stars 28.63k forks source link

url: deleting properties has no effect #1591

Closed silverwind closed 9 years ago

silverwind commented 9 years ago

Looks like deleting properties no longer has an effect because the properties are getters/setters. Encountered in https://github.com/npm/npm/blob/master/lib/config/nerf-dart.js

The question is, do we want to/can support this with getters/setters at all, or are we fine with it breaking? If we want to break it, we propable need to patch npm to use uri.prop = null or uri.prop = '' instead of delete uri.prop.

1.8.1

> uri = url.parse("https://registry.lvh.me:8661/")
> delete uri.protocol
> uri.format()
'//registry.lvh.me:8661/'

2.0.0

> uri = url.parse("https://registry.lvh.me:8661/")
> delete uri.protocol
> uri.format()
'https://registry.lvh.me:8661/'

cc: @petkaantonov @domenic @rvagg @othiym23

petkaantonov commented 9 years ago

The performance is not based on accesssors (except eager .format() call for .href), everything was made an accessor for consistency, for enabling browser similarity (which seems to be a goal of url module although it's currently nothing like that) and for better sanity, e.g. props can be validated and are reflected in other propd.

Also url is not a dictionary or an associative array but an object instance of Url...

chrisdickinson commented 9 years ago

@mikeal:

The assumption we were under when we agreed to take the change was that the only breaking change in clone() behavior

I probably did a bad job of explaining the other breaking change I was worried about, but here it is, for posterity:

parsed = url.parse('http://google.com/path/name?q=3')
parsed.hostname = 'ok.com'
parsed.host = null
console.log(url.format(parsed))

Before this changefeature, this would log 'http://ok.com/path/name?q=3', after this changefeature it will log 'http:///path/name?q=3'. That is, the order users change the properties in matters and can induce breaking behavior.

petkaantonov commented 9 years ago

@mikeal I think you mean before we decided to make everything an accessor (like in browsers).

In browsers host is just a hostname and port, it doesnt make sense to set hostname and host at the same time. You either set port and hostname separately or you set them together from one string using the host setter.

jcrugzz commented 9 years ago

I have seen the objects returned from url.parse() be used as if they were regular old object literals quite extensively. As @chrisdickinson points out, this changes the assumptions that might exist for some developers (including myself). I'm +1 on reverting this back until 3.0.0 so there is no scrambling to get things fixed before dropping the official 2.0.0

rvagg commented 9 years ago

the fact that you can pass the object in to http.request() even encourages you to think of it as a plain object

mikeal commented 9 years ago

quick question: if someone wanted this perf gain in their app today couldn't they just import it from npm and set url.parse to this version in the npm module? they could even use the --require flag to make sure it happens before any other modules get loaded and parse some urls.

jcrugzz commented 9 years ago

@rvagg exactly, my mind was trained to think of it as such.

chrisdickinson commented 9 years ago

@mikeal That would run into similar issues as --use-strict, but would be viable for folks to try it out ahead of time. It'd be roughly equivalent to a feature flag, I think.

mikeal commented 9 years ago

@chrisdickinson ya, that's what I figured. that might be a better path to getting the ecosystem to update than taking more code in to core that is behind a flag we may never take out from behind the flag.

petkaantonov commented 9 years ago

the npm module is completely different than this all accessors version

silverwind commented 9 years ago

Good call on the revert. What remains to be researched is why my proposed npm patch fails npm's tests, but otherwise this is resolved. Thanks everyone.

othiym23 commented 9 years ago

This will probably find its way back to the TC at some point, but as I explain in npm/npm#8163, @isaacs and I don't think the right thing to do is to change npm to match the new url interface. I'm happy to discuss our reasoning, but ultimately @isaacs made the call, and I agreed, that this set of changes is sufficiently problematic to require a lot more discussion and careful planning to land.

gx0r commented 9 years ago

Interesting...I suppose on the one hand, for any API, as an API user, I shouldn't expect delete to "work" because a property could be on a prototype. On the other hand, I wouldn't expect the shape of the object to change from Node version to version. Urlgeddon! ;-)

BTW nice work @petkaantonov. Do you know if there are techempower benchmarks showing the improvements?