-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Add HTMLAllCollection [[Call]], remove legacycaller special operation #2932
Conversation
source
Outdated
@@ -7091,6 +7092,11 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute | |||
different (ab)uses of its methods to all end up returning something, and that it can be called as | |||
a function as an alternative to property access.</p> | |||
|
|||
<p>Objects that implement the <code>HTMLAllCollection</code> are <span data-x="legacy platform |
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.
Missing word "interface"
source
Outdated
<p>Objects that implement the <code>HTMLAllCollection</code> are <span data-x="legacy platform | ||
object">legacy platform objects</span> with an additonal <a | ||
href="#HTMLAllCollection-call">[[Call]]</a> internal method described in the subsection | ||
below.</p> |
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'd rather the <a>
be "the subsection below". Also, probably "section" instead of "subsection"; who knows how deep it is nested (and thus how many "sub"s are necessary).
source
Outdated
@@ -7163,7 +7169,8 @@ interface <dfn>HTMLAllCollection</dfn> { | |||
element(s)</span> from this <code>HTMLAllCollection</code> given <var>name</var>.</p> | |||
|
|||
<p>The <dfn><code data-x="dom-HTMLAllCollection-item">item(<var>nameOrIndex</var>)</code></dfn> | |||
method (and the <code data-x="">legacycaller</code> behavior) must run the following steps:</p> | |||
method (and the <a href="#HTMLAllCollection-call">[[Call]]</a> internal method) must run the |
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 wouldn't include this here as it makes there be two normative definitions of [[Call]]
source
Outdated
<ol> | ||
<li><p>Let <var>result</var> be the result of performing the steps listed in the description of | ||
the <code data-x="dom-HTMLAllCollection-item">item</code> method on <var>thisArgument</var> with | ||
<var>argumentsList</var>[0] as argument.</p></li> |
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 guess we should really refactor these steps into a separate named algorithm.
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.
Done, though I'm not sure of the name.
I think you have to rebase on master. Sorry about that. |
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.
Another thing is that I'd like to address whatwg/webidl#407 if possible and convenient. In other words, deciding if document.all
is a constructor. Chrome says yes, Firefox says no.
@@ -7101,7 +7106,7 @@ interface <dfn>HTMLAllCollection</dfn> { | |||
readonly attribute unsigned long <span data-x="dom-HTMLAllCollection-length">length</span>; | |||
getter <span>Element</span>? (unsigned long index); | |||
getter (<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-namedItem">namedItem</span>(DOMString name); | |||
legacycaller (<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-item">item</span>(optional DOMString nameOrIndex); | |||
(<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-item">item</span>(optional DOMString nameOrIndex); |
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.
Would be good to add a comment in IDL about the fact that HTMLAllCollection
instances implement a [[Call]]. Even better if it's linked like for "intentionally" in HTMLUnknownElement
's IDL.
source
Outdated
<ol> | ||
<li><p>Let <var>result</var> be the result of <span | ||
data-x="concept-get-all-named-or-indexed">getting the "all"-named or indexed element(s)</span> | ||
from this <code>HTMLAllCollection</code> given <var>argumentsList</var>[0].</p></li> |
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.
If argumentsList's length is 0, it might be undefined behavior. Infra says, "The index cannot be out-of-bounds, except when used with exists." We don't use "exists" here, but there is a "was not provided" check in the algorithm. Either way I'd say it'll save us some headache if we just say "argumentsList[0] if argumentsList[0] exists".
OTOH, if argumentsList[0] is provided, it must first be converted to a IDL DOMString.
Another point of interest/headache is if argumentsList[0] is the ES value undefined. Per Web IDL right now it must be ignored as the parameter is optional. But on both Chrome and Firefox undefined is treated as 'undefined'
. Additionally Firefox throws if no argument is passed to document.all
or document.all.item
, against the spec; i.e. it's not treating the argument as optional at all.
A piece of good news is that branding check for thisArgument as a Document seems unnecessary though.
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.
Either way I'd say it'll save us some headache if we just say "argumentsList[0] if argumentsList[0] exists".
That's a good point. I thought I'd somehow get away with being hand-wavy here, but looks like I didn't. :-P
Another point of interest/headache is if argumentsList[0] is the ES value undefined. Per Web IDL right now it must be ignored as the parameter is optional. But on both Chrome and Firefox undefined is treated as 'undefined'. Additionally Firefox throws if no argument is passed to document.all or document.all.item, against the spec; i.e. it's not treating the argument as optional at all.
So Firefox's behavior is actually implementing legacycaller (HTMLCollection or Element)? item(DOMString nameOrIndex);
, right (i.e. without the optional argument)? Safari seems to be doing the same thing as Chrome, with a little twist: document.all.item()
is the same as document.all.item(undefined)
i.e. it treats it as "undefined"
, but document.all()
always returns undefined
.
Also worth noting that Chrome and Safari return undefined
instead of null
when they can't find a node.
Do we know what IE does?
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.
A piece of good news is that branding check for thisArgument as a Document seems unnecessary though.
Probably worth testing.
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.
Do we know what IE does?
I wrote a test file to be run on Edge. Seems like it does the exact same thing as Chrome.
A piece of good news is that branding check for thisArgument as a Document seems unnecessary though.
Probably worth testing.
Yep, the same behavior is present on all popular browsers regarding document.all()
's branding check.
The full results are available at: https://github.com/TimothyGu/document-all-undefined/blob/master/index.html. There are multiple instances of convergence we can spec.
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.
There are multiple instances of convergence we can spec.
Do you want to just go-ahead and push those to this PR?
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.
@tobie No commit access to this repo 😕
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.
@TimothyGu oh, right. I assumed checking "Allow edits from maintainers" was enough. Let me fix that.
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.
Is the goal here just to keep someone else from putting legacycaller on some interface? It's not clear to me why the spec (and possibly implementation) churn here is that desirable. In practice, at least for Gecko, we'd just leave legacycaller in our IDL, because the thing that needs to spit out the [[Call]] uses the IDL as input anyway... |
That, plus perhaps a general principle that constructs used for a single object on the platform should not get dedicated IDL syntax. |
And if the worry is that people will misuse |
@bzbarsky this was a proposed solution to whatwg/webidl#408, based on the fact that HTMLAllCollection is the only legacycaller with [[Call]]. |
Yes, I understand that. |
source
Outdated
|
||
<ol> | ||
<li><p>Let <var>result</var> be the result of <span | ||
data-x="concept-get-all-named-or-indexed">getting the "all"-named or indexed element(s)</span> |
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.
argumentsList is a list of ES Values. concept-get-all-named-or-indexed takes as input an IDL value. This is the main problem with trying to hand-define this instead of using IDL: you end up having to carefully reinvent parts of the IDL spec...
I don't mind backing out of this. We just need to address whatwg/webidl#408 differently. |
I guess we can do this on the principle that one-offs don't belong in IDL. We do need to make the actual algorithm make sense in terms of ES vs IDL values, though. |
I think
Agreed. I'll try to fix this while tackling #2932 (comment). |
I have addressed the issues @bzbarsky and I noted earlier. I have also made the change to return However, I also found even more complications to Web compatibility regarding this excrescence. It seems at least Chrome supports a weird two-argument form of // If there is a second argument it is the index of the item we want. The good news is that this feature is used very very rarely (0.000002% according to Chrome's UseCounter), and this special treatment does not extend to Another thing I noticed is that relatively recently WebKit changed its behavior regarding HTMLAllCollection to be spec-compliant, and therefore not consistent with any other browsers except for Firefox (mostly). 😕 CC'ing @samweinig who made that change. |
@TimothyGu I think we should stick with the existing spec/what was in IDL for null vs. undefined. It's been in the spec a long time, and we shouldn't be punishing Firefox and WebKit for following the spec. We need some WPTs for it, to be sure, but we shouldn't change it. |
source
Outdated
@@ -7247,9 +7250,15 @@ interface <dfn>HTMLAllCollection</dfn> { | |||
<h6 id="HTMLAllCollection-call">[[Call]] ( <var>thisArgument</var>, <var>argumentsList</var> )</h6> | |||
|
|||
<ol> | |||
<li><p>If <var>argumentsList</var>'s length is zero, return null.</p></li> |
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.
Lists have sizes, not lengths, per Infra.
So things to test so far:
what else? |
Sounds fair. Note that even Firefox isn't 100% compliant right now, as it throws when there's no argument. I'm unable to test latest Safari due to its unavailability on Sauce Labs and my not having a Mac. Some more test cases I thought of:
The following tests I thought of were already tested:
|
I think another thing is |
@annevk Yes, that would be something to test as well. However, current Web IDL spec doesn't do such a check, nor does any of the browsers I tested. |
All, a new batch of stuff.
|
Tests are now available at web-platform-tests/wpt#7254! |
source
Outdated
@@ -7101,7 +7106,11 @@ interface <dfn>HTMLAllCollection</dfn> { | |||
readonly attribute unsigned long <span data-x="dom-HTMLAllCollection-length">length</span>; | |||
getter <span>Element</span>? (unsigned long index); | |||
getter (<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-namedItem">namedItem</span>(DOMString name); | |||
legacycaller (<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-item">item</span>(optional DOMString nameOrIndex); | |||
(<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-item-noargs">item</span>(); | |||
(<span>HTMLCollection</span> or <span>Element</span>)? <span data-x="dom-HTMLAllCollection-item">item</span>(DOMString nameOrIndex); |
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.
Given the browser incompatibility here, I think we can align with Safari (1/4) and do optional arguments. I will push a commit.
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.
Oh, I see, Safari doesn't do optional arguments, it coerces undefined to a string. So... let's align with Firefox then.
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.
No, wait, Safari tech preview does optional arguments.
Basically given the non-interop here let's converge on Safari tech preview, which has done the best job staying up to date with the spec. Still working on it.
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.
So I changed this to align with the existing spec and with Safari. I think that's better than changing the spec out from under them, as they've been the ones that kept most up to date.
I'll work on the tests next.
data-x="">Function.prototype.call.call(document.all, null, "x")</code> will still search for | ||
elements. (<code data-x="">document.all.call</code> does not exist, since <code | ||
data-x="">document.all</code> does not inherit from <code | ||
data-x="">Function.prototype</code>.)</p> |
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.
You mean HTMLAllCollection
does not inherit from Function.prototype
? How is HTMLAllCollection
different from other interfaces in that regard? Can't be due to the custom [[Call]]
or is it?
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.
Yeah that's it.
Sure, but note: all browsers were consistently against the spec regarding This is different from #2932 (comment), where Safari TP and Firefox act the same way. The |
I think it's more important to play nicely with browsers that have taken pains to be spec-compliant, than it is to conform to the majority of browsers which haven't been paying attention---at least in cases where we don't believe there to be any compat concerns. Would either of you mind reviewing this and the tests, now that I've stuck my fingers in them and so it'd be good to get a review of my work? |
@domenic Your changes LGTM. |
This ended up being editorial since we preserved the spec behavior (which was last touched in 93cc395). But I'll take this opportunity to file browser bugs now that @TimothyGu has contributed a great comprehensive test suite. |
This makes document.all(undefined) behave like document.item(undefined). There was already a test for this, that got out of sync with the spec: https://github.com/w3c/web-platform-tests/blob/b6d42d0174fd24bda0802f8a55ee46381092ef80/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html#L209 #2932 Safari passes this test: https://wpt.fyi/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html?sha=13eaad17a4
Depends on whatwg/webidl#412.