Bug 76736

Summary: window.getMatchedCSSRules() not supporting pseudo classes
Product: WebKit Reporter: Eric Guzman <epiceric24>
Component: CSSAssignee: Nobody <webkit-unassigned>
Status: RESOLVED INVALID    
Severity: Enhancement CC: dstorey, jackalmage, shanestephens
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: Unspecified   
Attachments:
Description Flags
Demo of getMatchedCSSRules bug none

Description Eric Guzman 2012-01-20 13:49:59 PST
Created attachment 123371 [details]
Demo of getMatchedCSSRules bug

What steps will reproduce the problem?
1. Create CSS rules that apply to an element (including pseudo-class selectors)
2. Call window.getMatchedCSSRules(domElement, pseudoClassString), with pseudoClassString corresponding to those used in step 1.

What is the expected result?
The method should return a rule list containing the rules with pseudo class selectors.

What happens instead?
It only returns a rule list with the non-pseudo class selectors.

I don't know why this method only seems to support pseudo element selectors, when the use case for pseudo class selectors seems more common (or at least easy enough to support).

It would also be convenient for the method to return all CSS rules matching an element including all pseudo classes/elements. Currently, if you want to get all of the CSS rules targeting the element (in one state or another), this method would need to be called repeatedly.

Another problem with the method is that if a pseudo argument is supplied, but no css rules match the pseudo, it will return the non-psuedo CSS rules. I think returning null is the appropriate behavior.

About Attachment
I've provided an html page which has a demo of the bug. The html page includes an element which is styled with pseudo classes/elements. A button on the page calls "getMatchedCSSRules(element, pseudo)" passing in the pseudo specified in the drop down. There is also a log that shows the cssText of the returned rules.
Comment 1 Shane Stephens 2012-02-08 19:59:24 PST
getMatchedCSSRules currently has no public specification, but as far as I can tell the second argument is not intended to accept pseudoClasses (i.e. it only accepts pseudoElements by design).

If you feel that (1) getMatchedCSSRules is an important feature for the web platform and (2) it should return pseudoClasses, then I would encourage you to propose the feature on www-style.
Comment 2 Tab Atkins Jr. 2012-04-04 19:55:37 PDT
Pseudo-classes and pseudo-elements are completely different things.  They have almost no relation, except for an unfortunate early design flaw that made their syntax identical, and which carried over due to IE.

The second argument to gMCR is solely for selecting pseudo-elements, because you can't actually get a reference to a pseudo-element normally to pass as the first argument.

So, the premise of the bug is incorrect - gMCR *never* took a pseudo-class string argument.  Further, it's conclusion is wrong - gMCR *does* return rules that only match due to pseudo-classes.  For example, in the following document you'll get both rules showing up in your console results: 

data:text/html;charset=utf-8,%3C!DOCTYPE%20html%3E%0A%3Cp%3Efoo%0A%3Cstyle%3E%0Ap%20%7B%20color%3A%20red%3B%20%7D%0A%3Afirst-child%20%7B%20background%3A%20blue%3B%20%7D%0A%3C%2Fstyle%3E%0A%3Cscript%3E%0Aconsole.log(getMatchedCSSRules(document.querySelector('p')))%3B%0A%3C%2Fscript%3E

It'll even work for :hover rules *if you make the gMCR call while the element is being hovered*.  Example (press the button to call gMCR and log it to console): 

data:text/html;charset=utf-8,%3C!DOCTYPE%20html%3E%0A%3Cp%3Efoo%3Cbutton%3Ebar%3C%2Fbutton%3E%0A%3Cstyle%3E%0Ap%20%7B%20color%3A%20red%3B%20%7D%0Ap%3Afirst-child%20%7B%20background%3A%20blue%3B%20%7D%0Ap%3Ahover%20%7B%20background%3A%20green%3B%20%7D%0A%3C%2Fstyle%3E%0A%3Cscript%3E%0Adocument.querySelector('button').onclick%20%3D%20function()%7B%20%0A%20%20console.log(getMatchedCSSRules(document.querySelector('p')))%3B%0A%7D%3B%0A%3C%2Fscript%3E

What it won't do, though, is return a rule with a ":hover" selector when the element isn't being hovered, because that rule isn't currently matching the element.

If you'd like to be get the selectors that would apply when an element is hovered, we'd need an additional argument letting us specify some state that we should pretend the element matches.  

This sounds like a fine idea (it's needed if you want a relatively easy way to achieve functionality like what Inspector does when it shows you the rules that apply during :hover), but it needs specification.

Given that this gMCR isn't specified *at all* right now, the right thing to do is fix that problem first and write a CSSOM subspec, then add this argument to the spec so we can implement it.
Comment 3 Tab Atkins Jr. 2012-04-04 19:59:17 PDT
(In reply to comment #0)
> Another problem with the method is that if a pseudo argument is supplied, but no css rules match the pseudo, it will return the non-psuedo CSS rules. I think returning null is the appropriate behavior.

Please file one bug per bug.  ^_^

This is half-valid.  If you specify a valid pseudo-element, and no rules match the pseudo, it returns null, as it should.  However, it you pass it a string that doesn't correspond to any pseudo (like getMatchedCSSRules(el, 'foo') ), then it just ignores the second argument and returns the rules that match the element normally.

I agree this isn't ideal behavior, as it's future-hostile (if we later add a ::foo pseudo-element, someone accidentally depending on that call returning the rules that match the passed element will break).  Please file a separate bug for this, with a title like "getMatchedCSSRules() should return null when the second argument is an unrecognized pseudo-element name".
Comment 4 David Storey 2012-04-05 10:56:30 PDT
(In reply to comment #2)

> What it won't do, though, is return a rule with a ":hover" selector when the element isn't being hovered, because that rule isn't currently matching the element.
> 
> If you'd like to be get the selectors that would apply when an element is hovered, we'd need an additional argument letting us specify some state that we should pretend the element matches.  
> 
> This sounds like a fine idea (it's needed if you want a relatively easy way to achieve functionality like what Inspector does when it shows you the rules that apply during :hover), but it needs specification.

Yes, this is exactly the kind of thing we want to be able to do.
> 
> Given that this gMCR isn't specified *at all* right now, the right thing to do is fix that problem first and write a CSSOM subspec, then add this argument to the spec so we can implement it.

Yes, it would be great if we could get that argument. Should I file a bug in the CSS bugzilla or post on www-style first?
Comment 5 Tab Atkins Jr. 2012-04-05 11:02:00 PDT
I recommend first posting to www-style proposing to specify gMCR, then when you write the spec discuss adding the additional argument.  Our current implementation counts as a simple experiment, so it's okay to extend the API as we spec it.
Comment 6 Eric Guzman 2012-04-05 11:50:46 PDT
Thanks for the additional info, Tab, and thanks for the follow-up, David.

I created a bug for the method not returning null, as suggested: https://bugs.webkit.org/show_bug.cgi?id=83298.