Bug Tracker

Ticket #13182 (closed bug: fixed)

Opened 21 months ago

Last modified 20 months ago

nested has selectors broken in IE7 & IE8 in versions 1.8.2+

Reported by: anonymous Owned by: gibson042
Priority: low Milestone: 1.9.1
Component: selector Version: 1.8.2
Keywords: Cc:
Blocking: Blocked by:

Description

I have a rather complex DOM structure and I am doing some rather involved queries to get to data stored in this structure. (Questionable, I know) I recently took the initiative and updated our reference to jQuery to use the latest version and suddenly things started breaking. Specifically, queries that were looking for attributes inside of a :has. Below is a sample query that works flawlessly (albeit slowly) in 1.8.1 but fails in 1.8.2+.

This fails in IE7 but works for IE8 $('.SomeClass:has(div:has(div[SomeAttr=SomeValue]))');

The following works in IE8 but not in IE7 $('.SomeClass:has(div:has(div [SomeAttr=SomeValue]))');

Note the additional space after the last div.

In addition, I cannot get the following slightly more complex query to work at all in IE7 or IE8 using 1.8.2+.

$('.SomeClass:has(div:has(div[SomeAttr=SomeValue],div[SomeOtherAttr=SomeOtherValue]))');

I have not had the time to step through the developer versions of the code to see if I can find the culprit, but I did step back through versions of jQuery and found that the problems went away when I stepped back into 1.8.1. (We had been on 1.7.x before I jumped up to 1.8.3)

I'll try to monitor this ticket and respond to any questions the jQuery team may have.

Change History

comment:1 Changed 21 months ago by dmethvin

  • Owner set to anonymous
  • Status changed from new to pending

The first thing we'd want is a simple test case that demonstrates the problem. Can you create one on jsfiddle.net or jsbin.com?

comment:2 Changed 21 months ago by anonymous

  • Status changed from pending to new

Sorry, I thought I had provided enough information. As it turns out, I had the bug a bit off. But it is similar. The error just goes in the other direction. below is the link to the fiddler for this:

 http://jsfiddle.net/RwR8U/

Just in case things do not work right, here is my html and js:

-HTML-

<div class="tile">
  <div>
    <div someAttr='boo'>
  </div>
</div>
<div class="tile">
  <div>
    <div someAttr='foo'>
  </div>
</div>
<div class="tile">
  <div>
    <div someAttr='boo'>
  </div>
</div>
<div class="tile">
  <div>
    <div someAttr='boo'>
  </div>
</div>
<div id="result"></div>

-JS-

$(document).ready(function(){
  $('#result').html($( '.tile:has(div:has(div [someAttr=foo]))' ).length);
});

To verify that things work right and then to reproduce the bug, do the following:

  • Launch this fiddler in IE9 (I used IE9 as its emulators for older versions matched the behavior i was seeing in native IE7).
  • Verify that JQ version 1.7.2 is currently being utilized
  • run the script
  • note that the result is 1 item (this is what it should be)
  • Launch the IE Dev Tools (F12) and switch the IE version to 7
  • Execute the script again against 1.7.2
  • note that the result is still 1 item (still good)
  • now switch the version to 1.8.2
  • run the script again (still in IE7 mode)
  • note that the result is now 2 (this value is incorrect!)
  • for an additional twist, remove the space between the last div and the [ and you will now get 0 items. However, after a bit of playing, I do believe that the space is required for proper use of this feature. Is this correct?

Please let me know if I can provide any additional information.

comment:3 follow-up: ↓ 5 Changed 21 months ago by anonymous

correction, try this one instead:

 http://jsfiddle.net/RwR8U/5/

it should have the space between the last div and the [ as described...

comment:4 Changed 21 months ago by dmethvin

  • Status changed from new to pending

Can you confirm that this test case works as you expect, once all the divs are properly closed?

 http://jsfiddle.net/RwR8U/7/

comment:5 in reply to: ↑ 3 Changed 21 months ago by gibson042

Replying to anonymous:

correction, try this one instead:

 http://jsfiddle.net/RwR8U/5/

it should have the space between the last div and the [ as described...

Whitespace between div and [someAttr=foo] is not meaningless; it is a descendant combinator. div [someAttr=foo] matches any element with attribute "someAttr" having value "foo" that is contained within a div. Any past interpretation of it as equivalent to div[someAttr=foo] (which matches a div with attribute "someAttr" having value "foo") was a bug on our part.

comment:6 Changed 21 months ago by anonymous

  • Status changed from pending to new

erg... copy, paste and fast editing. I'll get back to this in a few days when i have time again. I can guarantee that the odd behavior is there and that swapping out versions will make it go away though.

And at least i know that there was some weirdness around the spaces in the past. in my case, the div should contain an attribute with the value. and i was not seeing consistent behavior. Again, I'll run some tests in a few days when i have time to breathe again.

Thanks jQuery team.

comment:7 Changed 21 months ago by anonymous

Ended up with a little free time today so, start by visiting this:

 http://jsfiddle.net/XcNCz/

  • Then fire up IE7
  • Verify that JQ 1.7.2 is being utilized
  • Run the test
  • Note 2 cats are found and that 3 cats and dogs are found (correct)
  • Switch the version to 1.8.2
  • Run the test
  • Note that zero of either are located (bad)

This is what I was seeing originally in my app, and you were right about my quickly hacked tags creating a separate issue.

I've rolled back to version 1.7.2 for now in my app as I know for a fact that it works. And I only see this bad behavior in IE7 (Tested IE7, 8, 9, FF and Chrome). I would love to get all stabby on that darn browser...

comment:8 Changed 21 months ago by gibson042

  • Status changed from new to assigned
  • Component changed from unfiled to selector
  • Summary changed from complex has attribute selectors broken in IE7 & IE8 in versions 1.8.2+ to nested has selectors broken in IE7 & IE8 in versions 1.8.2+
  • Priority changed from undecided to low
  • Version changed from git to 1.8.2
  • Milestone changed from None to 1.next
  • Owner changed from anonymous to gibson042

Well, you sure get my vote for most obscure bug of the month. This one was a doozy, basically coming down to element ancestry cache keys conflicting for sub-runs within a parent selector containing nested :has checks... even writing a  unit test took about 15 minutes!

This will be fixed in 1.9.1, but I strongly recommend refactoring. Even non-nested :has selectors exhibit pretty bad performance, but nesting makes it an order of magnitude worse, and—since the same can be  achieved with descendant combinators—is always unnecessary.

Last edited 21 months ago by gibson042 (previous) (diff)

comment:9 Changed 21 months ago by Richard Gibson

  • Status changed from assigned to closed
  • Resolution set to fixed

Fix #13182: update Sizzle

Changeset: d8690344b7ba8c0b4a1eb7d57c7c0fcdbbc0ba7c

comment:10 Changed 21 months ago by Richard Gibson

Fix #13182: update Sizzle

Changeset: 2f0756b5341eb94ae540de20b9756762dc0a4144

comment:11 Changed 21 months ago by gibson042

  • Milestone changed from 1.next to 1.9.1

comment:12 Changed 20 months ago by anonymous

Hey, thanks for looking into that so quickly. Yes, I know that the selector is HORRID and i really should not be doing it. I will be refactoring that chunk of code at the very next chance i get. was a very bad design decision on my part to do what i did. live and learn. Thanks again jQuery team!!

Note: See TracTickets for help on using tickets.