-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
url: use symbol properties correctly in URL class #10906
Conversation
Regarding toStringTag, this is actually a controversial part of the Web IDL spec. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244. I would suggest following Chrome's version, of just putting it as a data property on the prototype, but I am somewhat biased there :). +1 to fixing the inspect thing. |
FWIW, here are where the browsers stand at the moment: Chrome Canary 57.0.2986.0:
Firefox Nightly 53.0a1
Safari 10.0.2
|
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.
LGTM. I'm trying to recall if there is a test that verifies the toStringTag. If not, it would be worthwhile to add one here. Good to go either way tho after CI
There are tests( |
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.
I think it's OK to move closer to the spec even when the browsers don't at the moment, but I am a little curious about the performance hit to new URL
, as brought up in https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244?
Let me mention the following error I faced on the branch:
Potentially, the type annotation in the error message was changed to |
Indeed, I see a nontrivial performance drop after this PR 😢 As recommended by @domenic, Chrome's behavior (which does not change performance significantly) is now adopted. CI can't be launched right now due to overcrowding. |
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.
Not too happy with losing the URLPrototype
. Please hold off on landing this so we can explore the options and the perf hit a bit more.
For performance and consistency with Chrome.
After thinking about this issue a bit more, I am still convinced Chrome's behavior is currently the best one. It provides reasonable behaviors in all cases. In the only case it deviates from the Web IDL Standard, it follows the behavior a JS programmer would expect without reading DOM specs ( See below for a comparison table. Explanations for certain table headings are provided also.
|
getter | Cannot set property origin of [object Object] which has only a getter |
---|---|
spec | Cannot set property origin of [object URLPrototype] which has only a getter |
data prop on proto | Cannot set property origin of [object URL] which has only a getter |
Performance
The performance hit for using the specification behavior is unfortunately non-trivial.
getter vs. spec
improvement confidence p.value
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="auth" -9.25 % *** 1.888128e-08
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="dot" -15.10 % *** 3.261167e-25
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="idn" -13.13 % *** 1.746267e-16
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="long" -8.71 % *** 5.557978e-19
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="percent" -16.61 % *** 1.859190e-22
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="short" -14.46 % *** 3.478541e-27
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="special" -15.36 % *** 1.582933e-27
getter vs. data property on proto
improvement confidence p.value
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="auth" 0.76 % 0.53752737
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="dot" -0.16 % 0.83467996
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="idn" -0.67 % 0.46420488
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="long" -0.78 % 0.28338187
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="percent" 1.53 % 0.05135193
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="short" -1.90 % * 0.01902907
url/legacy-vs-whatwg-url-parse.js n=100000 method="whatwg" type="special" 1.44 % 0.09545987
Consistency
No browsers currently implement the spec literally or getters.
This PR implements Chrome's behavior.
Edge, Firefox, and Safari do not implement @@toStringTag
for DOM interfaces at this moment.
Ok. I'll still likely play around with it a bit more to see what (if anything) we can do here to ensure that we're entirely spec compliant but I'll clear my objection and sign off |
Will apply tomorrow if no objections. |
Please do so. I'd be interested in an alternative as well. |
PR-URL: #10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Even though this is not fully Web IDL spec-compliant, it is arguably the best we can do. Following the spec would mean non-trivial performance deterioration (10% when parsing a medium-length URL), while the current getter behavior is not adopted by any implementer, and it causes some spec ambiguity when the getter is called with !(this instanceof URL). This commit adopts Chrome's behavior, and is consistent with ECMAScript-defined classes while providing reasonable behaviors for corner cases as well. Until the Web IDL spec is changed one way or another, this is the way to go. PR-URL: #10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: nodejs#10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Even though this is not fully Web IDL spec-compliant, it is arguably the best we can do. Following the spec would mean non-trivial performance deterioration (10% when parsing a medium-length URL), while the current getter behavior is not adopted by any implementer, and it causes some spec ambiguity when the getter is called with !(this instanceof URL). This commit adopts Chrome's behavior, and is consistent with ECMAScript-defined classes while providing reasonable behaviors for corner cases as well. Until the Web IDL spec is changed one way or another, this is the way to go. PR-URL: nodejs#10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: #10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Even though this is not fully Web IDL spec-compliant, it is arguably the best we can do. Following the spec would mean non-trivial performance deterioration (10% when parsing a medium-length URL), while the current getter behavior is not adopted by any implementer, and it causes some spec ambiguity when the getter is called with !(this instanceof URL). This commit adopts Chrome's behavior, and is consistent with ECMAScript-defined classes while providing reasonable behaviors for corner cases as well. Until the Web IDL spec is changed one way or another, this is the way to go. PR-URL: #10906 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This PR has two commits, both concerning the usage of symbol properties.
The first is to avoid using a getter for
@@toStringTag
. It does mean that parts of #10562 are reverted. This is done for multiple reasons:Web IDL says "the object must, at the time it is created, have a property whose name is the @@toStringTag symbol and whose value is the specified string." This implies that the object itself must possess the property, not its [[Prototype]].
From the same quote above, the spec says the property must have a value, (not a getter). Elsewhere in the spec, the distinction between getter, setter, and value of a property is always well-defined, and there is no reason to assume otherwise for this instance.
Ambiguity of behavior when something like this happens:
Web IDL is usually fairly strict with
this
values (see operations/methods, getters and setters). In fact, all of the following will result in an error in the browser:However, because of the second concern above, no getter for
@@toStringTag
is defined in the spec, and therefore no algorithms exist for dealing with this situation: whether the getter should return'URL'
,'URLPrototype'
,''
,undefined
, or throw an error cannot be reasonably decided. Currently, evenObject.getOwnPropertyDescriptor(URL.prototype, Symbol.toStringTag).get.call(null)
returns'URLPrototype'
, which makes little sense.This change does also need to be applied to
URLSearchParams
class. I will do so in a subsequent PR.The second is arguably less controversial. The issue is that an undocumented but public
inspect()
exists onURL.prototype
, even though it is not part of the URL Standard. It was first raised by @watilde in #10857 (comment). This PR fixes this issue by renaming the property to an internal symbol reserved for inspect method, which is already howURLSearchParams
' inspection operates. Tests are adjusted accordingly./cc @nodejs/url, @watilde
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
url-whatwg