Sitelet https://github.com/nodejs/node/issues/1591
Skip to content

url: deleting properties has no effect #1591

Description

@silverwind

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

Activity

  1. added
    urlIssues and PRs related to the legacy built-in url module.
    on May 2, 2015
  2. changed the title [-]url: deleting properties no longer supported[/-] [+]url: deleting properties has no effect[/+] on May 2, 2015
  3. petkaantonov commented on May 2, 2015

    @petkaantonov
    Contributor

    there is no real utility in deleting like this, uri.protocol = null; etc has same effect (and is more efficient to boot), even with plain objects.

  4. silverwind commented on May 2, 2015

    @silverwind
    ContributorAuthor

    Yeah, delete perf is horrible, I'm all for not supporting it anymore. What do you think about setting configurable = false on all props to stop delete from deleting the getters/setters?

  5. added a commit that references this issue on May 2, 2015
  6. added this to the 2.0.0 milestone on May 2, 2015
  7. added a commit that references this issue on May 2, 2015
  8. rvagg commented on May 2, 2015

    @rvagg
    Member

    I'm pretty sure delete url.prop is in fairly high usage in userland, if we can support this then we probably should because otherwise we're going to be dealing with lots of bug reports

  9. silverwind commented on May 2, 2015

    @silverwind
    ContributorAuthor

    I don't think this can be fixed without a fundamental change in the module (and likely a big perf loss).

    My first idea was to set configurable: false on all props in the hopes it will throw an error on delete, but that just silently fails. It does return false but I guess few check the return value of delete.

  10. monsanto commented on May 2, 2015

    @monsanto
    Contributor

    @silverwind it will throw an error in strict mode (at least the case you linked to, it wont for things on the prototype unfortunately)

  11. silverwind commented on May 2, 2015

    @silverwind
    ContributorAuthor

    @monsanto thanks, I incidentally just read about that. Won't help as these properties are all on the prototype.

  12. monsanto commented on May 2, 2015

    @monsanto
    Contributor

    How slow would it be to add the getters on the instance itself for a few releases to help people migrate? Declare the functions themselves outside of the constructor so we don't get into bad closures-and-hidden-classes territory, of course.

    Of course it wouldn't help for people who don't use strict mode...

  13. petkaantonov commented on May 2, 2015

    @petkaantonov
    Contributor

    property definition is absurdly slow even if you have static functions

  14. silverwind commented on May 2, 2015

    @silverwind
    ContributorAuthor

    Hmm I think Object.observe could catch that deletion and set the prop to null.

  15. silverwind commented on May 2, 2015

    @silverwind
    ContributorAuthor

    Nope, Object.observe won't work on the prototype. 😢

  16. 39 remaining items

  17. mikeal commented on May 3, 2015

    @mikeal
    Contributor

    I think it would be better to back it out then. We'll want to re-evaluate if this is worth landing being that there is no way to fix this behavior without using proxies and we still don't know when those will land and what perf impact they'll have when they do. The assumption we were under when we agreed to take the change was that the only breaking change in clone() behavior, I'm not sure the TC would find this level of breakage acceptable or not so it's better just to put it back through the process.

  18. petkaantonov commented on May 3, 2015

    @petkaantonov
    Contributor

    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...

  19. chrisdickinson commented on May 3, 2015

    @chrisdickinson
    Contributor

    @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.

  20. petkaantonov commented on May 3, 2015

    @petkaantonov
    Contributor

    @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.

  21. jcrugzz commented on May 3, 2015

    @jcrugzz

    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

  22. rvagg commented on May 3, 2015

    @rvagg
    Member

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

  23. mikeal commented on May 3, 2015

    @mikeal
    Contributor

    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.

  24. jcrugzz commented on May 3, 2015

    @jcrugzz

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

  25. chrisdickinson commented on May 3, 2015

    @chrisdickinson
    Contributor

    @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.

  26. mikeal commented on May 3, 2015

    @mikeal
    Contributor

    @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.

  27. petkaantonov commented on May 3, 2015

    @petkaantonov
    Contributor

    the npm module is completely different than this all accessors version

  28. silverwind commented on May 4, 2015

    @silverwind
    ContributorAuthor

    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.

  29. othiym23 commented on May 5, 2015

    @othiym23
    Contributor

    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.

  30. gx0r commented on May 5, 2015

    @gx0r

    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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    urlIssues and PRs related to the legacy built-in url module.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions