You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
APIs using this algorithm […] may optionally provide […] which pseudo-elements are allowed to show up in the match list, if any. If not specified, this defaults to allowing all pseudo-elements.
As far as I understand, "allowing all pseudo-elements" means that pseudo-elements are effectively ignored during matching. For example, document.body.matches('body::after') should return true. This seems backwards, and indeed Firefox 44 and Chromium 49 both return false.
The DOM spec should probably add “with an empty list of pseudo-elements” near “the result of match a selector against an element”.
Other Selectors-related APIs likely have similar issues.
I don't really understand the setup here. @tabatkins how can CSS just return a pseudo-element? The engine needs to have the context of a node or a set of nodes, no?
Augh, I didn't pay enough attention to the OP here anyway.
Wrt the OP, document.body.matches('body::after') definitely returns false as currently specified. "Evaluate the selector" ends up returning just the body's ::after pseudo-element, and then "match the selector against an element" doesn't find <body> in the list, so you get false, as expected. So, DOM doesn't need to do anything here.
querySelector() does need to pass an empty list of allowed pseudo-elements, tho, since otherwise you get nonsensical results (there's no way to reflect a pseudo-element as a JS object right now).
Yes, pseudo-elements (the spec concept) have a pointer to their originating element. If/when we expose pseudo-elements to JS, they'll similarly have a parentElement attribute.
Thanks, and the pseudo-element gets returned because the selector was parsed successfully and it is the last thing in the list? No out-of-band information involved?
Your first question confuses me a little bit - the pseudo-element gets returned because that's what the selector selects. Unclear what out-of-band information you could be talking about.
I still don't understand why it would default to allowing all pseudo-elements. This algorithm is specifically designed for querySelector() and matches(). Why make the invocation more complicated?
Does it have any invocations other than those two APIs?
Looks like this was fixed back in 2017. The algo was rewritten to no longer talk about pseudo-elements at all, so calling it with the selector body::after will just fail to return any matches.
As HTML is still calling the algorithm correctly, we can go ahead and close this.
My understanding is that you are referring to the rewrite of match a selector against a tree. The new version, which is still the same version today, do talk about pseudo-elements:
For each possible pseudo-element associated with element that is one of the pseudo-elements allowed to show up in the match list, if the result of match a selector against a pseudo-element for the pseudo-element and selector is success, add the pseudo-element to the selector match list.
Activity
annevk commentedon Mar 5, 2016
I don't really understand the setup here. @tabatkins how can CSS just return a pseudo-element? The engine needs to have the context of a node or a set of nodes, no?
tabatkins commentedon Mar 7, 2016
The prose algorithm can return pseudos, because the result might be used by further prose algorithms that understand pseudo-elements.
Obviously there's not currently any way to surface pseudo-elements in JS.
annevk commentedon Mar 8, 2016
Don't you need to have a node and a pseudo? It seems like you're assuming the node tree and the layout tree are intertwined, which would be weird.
annevk commentedon Aug 17, 2016
@tabatkins ping.
tabatkins commentedon Aug 17, 2016
Augh, I didn't pay enough attention to the OP here anyway.
Wrt the OP,
document.body.matches('body::after')definitely returns false as currently specified. "Evaluate the selector" ends up returning just the body's ::after pseudo-element, and then "match the selector against an element" doesn't find<body>in the list, so you get false, as expected. So, DOM doesn't need to do anything here.querySelector()does need to pass an empty list of allowed pseudo-elements, tho, since otherwise you get nonsensical results (there's no way to reflect a pseudo-element as a JS object right now).annevk commentedon Aug 17, 2016
How can it return a pseudo-element though? Does that carry a pointer to the element?
tabatkins commentedon Aug 17, 2016
Yes, pseudo-elements (the spec concept) have a pointer to their originating element. If/when we expose pseudo-elements to JS, they'll similarly have a parentElement attribute.
annevk commentedon Aug 17, 2016
Thanks, and the pseudo-element gets returned because the selector was parsed successfully and it is the last thing in the list? No out-of-band information involved?
tabatkins commentedon Aug 17, 2016
Your first question confuses me a little bit - the pseudo-element gets returned because that's what the selector selects. Unclear what out-of-band information you could be talking about.
annevk commentedon Aug 17, 2016
I'm wondering if we're on the same page that the input to the algorithm is the selector and the node tree only.
tabatkins commentedon Aug 17, 2016
Yes, that's it. But the output isn't restricted to things from the node tree (it's nodes + pseudo-elements).
annevk commentedon Aug 18, 2016
I still don't understand why it would default to allowing all pseudo-elements. This algorithm is specifically designed for
querySelector()andmatches(). Why make the invocation more complicated?Does it have any invocations other than those two APIs?
annevk commentedon Mar 16, 2017
@tabatkins ping.
annevk commentedon Jul 9, 2026
@tabatkins thoughts?
tabatkins commentedon Jul 13, 2026
lol whoops, what a ping.
Looks like this was fixed back in 2017. The algo was rewritten to no longer talk about pseudo-elements at all, so calling it with the selector
body::afterwill just fail to return any matches.As HTML is still calling the algorithm correctly, we can go ahead and close this.
annevk commentedon Jul 14, 2026
Thanks!
cdoublev commentedon Jul 20, 2026
I am confused.
My understanding is that you are referring to the rewrite of match a selector against a tree. The new version, which is still the same version today, do talk about pseudo-elements:
tabatkins commentedon Jul 20, 2026
No, I'm referring to https://dom.spec.whatwg.org/#dom-element-matches, which calls "match a selector against an element".