Skip to content

Conversation

@cmcnulty
Copy link

Pull request to fix the disabled fieldset problem identified here:
#174

Wasn't sure if it was better to create a new assert or try to add on to the existing one.

@cmcnulty
Copy link
Author

Blargh, just realized that my tests broke a few nth selector tests. Will refactor the tests ASAP.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add tests for several types of inputs. Also, add a test for more a distant ancestor being disabled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll probably also want a guard... if I correctly understand #174 (comment), then IE6-7 are still hanging out to dry.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll probably also want a guard...

+1

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the notes - I have additional tests ready to go. Is there a convention for where new stuff should go in the index.html testbed? I broke a bunch of n-th tests by just adding a form in the middle - but there was definitely nothing explicitly in the index.html about which tests are going to be relying on which elements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No convention. Adding any HTML could be problematic given the specificity of some of our test selectors. It's just something we deal with.

node is failing the new test - browsers pass. what to do?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node.js test is failing this test - browsers are passing it. Not sure how to proceed on this!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly the same as IE6-7... break this assertion out into a "disabled fieldset (#174)" test and put in a userAgent guard so the broken phantomjs and IE clients skip it. 😢

Was able to remove options code, since browsers (mostly) agree that
options don't inherit disabledness
src/sizzle.js Outdated
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I completely understand the way the previous assert works, which is why I created a new assert - but it looks to me like some bytes could be shaved by integrating this into the previous assert, directly after the other push of :enabled, :disabled - IE8 won't run the test, but it will have already added enabled/disabled to buggyQSA (right?) and the triggering of the opera error doesn't seem to rely on the div content at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checking I just did, which I actually find hard to believe, suggest that it's not just IE8 throwing an exception on div.querySelectorAll(":enabled"), but IE8-11+ (that's right, even the latest available IE rejects :disabled and :enabled)! If that's correct, then this whole additional assert is unnecessary because any selector containing those tokens will fail and fall into our engine anyway. Unless isDisabled logic can fix another broken client, it looks like all you need to do here is update the range in the L653 support comment.

I think that also answers your confusion about the preceding assert (IE8 executes nothing after div.querySelectorAll(":enabled"), including rbuggyQSA.push( ":enabled", ":disabled" ), and only Opera 10-11 execute rbuggyQSA.push(",.*:") because other clients will have errored on div.querySelectorAll("*,:x") [which you correctly identify as independent of the div content]), but feel free to follow up with other questions. There's lots of pro-compression shortcuts in assert, like exception trapping and automatic div creation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how you tested, but I'm not getting any exceptions on :enabled or :disabled on IE11 on Windows 7 by just typing into the console.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I just found my problem: running the query on a detached node straight from document.createElement, which throws syntax errors on IE. It's worth noting because that's precisely what div is in the assert callbacks, so for this to work you'll want to do something like docElem.appendChild( div ).innerHTML = … à la L526.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, will do.

src/sizzle.js Outdated
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "fix" depends on the presence of the isDisabled prop - so should I test for it here? I seems extraneous since there are no known browser environments that would produce the error, but wouldn't have the isDisabled prop, on the other hand, adding the test now might future proof the code a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in getting back to you, but this particular mess troubled me enough that I filed a bug with the HTML standard: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24782

Until that's cleared up, let's just drop the option:disabled testing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't mind, I'm going to quote your notes from that issue:
referencing: http://www.whatwg.org/specs/web-apps/current-work/#selector-disabled

As for the DOM viewer :disabled test, I see failures with the following clients:
  • IE (all versions) erroneously fails to match o2 (option in a disabled group)
  • Safari<6 erroneously matches o3 (option in a disabled select)
  • Safari 6.0 erroneously matches o3 (option in a disabled select) and fails to match g2d; o2 (disabled group; option in a disabled group)
  • Opera<15 (Presto) erroneously matches o3; g4; o4 (option in a disabled select; group in a disabled select; option in a group in a disabled select)
  • Android (all versions) erroneously matches o3 (option in a disabled select)
<select id=s1><option disabled id=o1d></select>
<select id=s2><optgroup disabled id=g2d><option id=o2></select>
<select id=s3d disabled><option id=o3></select>
<select id=s4d disabled><optgroup id=g4><option id=o4></select>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm completely behind dropping option testing. Will check that in ASAP.

@gibson042
Copy link
Member

Do my observations at https://www.w3.org/Bugs/Public/show_bug.cgi?id=24782#c2 match yours? If so, we should be able to pave over more bugs by casting a wider net—in particular, detecting :enabled and :disabled as buggy when an option in a disabled select is matched by :disabled (IE<11+, Android<4.2+, Safari<6.1, Opera<15).

@cmcnulty
Copy link
Author

Agreed, that we could cast a wider net however we currently only have a mechanism for fixing IE, because only IE supplies the .isDisabled property. All other solutions require an expensive ancestor traversal, which has been rejected in the past.

@gibson042
Copy link
Member

That's true, but we now have a better picture of browser errors around this issue. Given that only IE messes up querySelectorAll(":disabled") under disabled fieldsets (per the support comment), we can leverage the capabilities of most other supported browsers to fix them:

return elem.disabled === true || elem.disabled === false && (
    elem.isDisabled === true ||
    support.matchesSelector && matches.call( elem, ":not(option):disabled" ) )

Then again, it does look pretty big now that I see it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked to make sure that putting:

^(?:input|select|textarea|button

into it's own variable and then doing a RegExp didn't save bytes - it didn't.

@gibson042
Copy link
Member

So using some shortcuts:

  • :can-disable (input, select, textarea, button, menuitem, fieldset)
  • :can-enable (:can-disable, a[href], area[href], link[href])

and ignoring option, optgroup, here's what 88 bytes or so can get us:

native Sizzle current Sizzle proposed
:disabled false negative IE: fieldset[disabled] :input all: fieldset[disabled] :input not IE: fieldset[disabled] :input
:enabled false negative - - IE: menuitem, fieldset, a[href], area[href], link[href]
:disabled false positive - IE: :not(:can-disable)[disabled] -
:enabled false positive IE: fieldset[disabled] :input all: fieldset[disabled] :input IE: :not(:can-enable) -

Is that right?

@gibson042
Copy link
Member

After much consternation, I ended up landing the broader #283 fix. But thanks a ton for this effort, and sorry about the extended delay.

@gibson042 gibson042 closed this Jan 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants