Bug Tracker

Ticket #3837 (closed bug: fixed)

Opened 6 years ago

Last modified 2 years ago

Complex selector using :not() can lead to an infinite loop

Reported by: dtetto Owned by: john
Priority: major Milestone: 1.3.1
Component: selector Version: 1.3
Keywords: Cc:
Blocking: Blocked by:

Description

Don't know exactly which part of the selector causes the bug, but: $('.container div:not(.excluded) div'); causes an infinite loop at line 1769 of jquery.js in Firefox 3. (It doesn't cause the loop in a recent WebKit nightly; I haven't tested in IE or Opera.)

This is a bug introduced in the RC for 1.3 (it didn't exist in beta 2, nor in jQuery 1.2).

Here's the full test case with links to some working variations to help isolate the problem:  http://www.babywhale.net/loop/final.php

Change History

comment:1 Changed 6 years ago by dtetto

Correction: The loop happens at  http://code.jquery.com/jquery-1.3.js line 1774.

comment:2 Changed 6 years ago by Thasmo

It only seems to freeze/loop if you enable the 'console' in firebug. Without enabling it, it works fine for me on FF 3.0.5.

comment:3 Changed 6 years ago by john

  • Owner set to john
  • Version set to 1.3
  • Component changed from unfilled to selector
  • Milestone changed from 1.3 to 1.3.1

comment:4 Changed 6 years ago by ashah

If it helps, I have found a similar problem in IE7 and Firefox 3.1 (disabling Firebug didn't help Firefox).

I am still investigating, but for me, have narrowed it down to this:

.find('> tbody:not(.row-template) > tr:not(.removed)')

Furthermore, I believe it is in this part of the selector:

('> tbody:not(.row-template))

I hope to provide a test case in a day or three when I get another spare moment...

comment:5 Changed 6 years ago by C.Johnson

I was having a similar problem (jQuery goes into infinite loop, causes script timeout error) and narrowed it down to the :not selector. Changing the code to use the .not() method fixed the script timeout.

The code that was failing in IE and Firefox 3:

$('div.postfooter div.rating a.ratebutton:not(.igray)').click(rateEntry);

The code that works:

$('div.postfooter div.rating a.ratebutton').not('.igray').click(rateEntry);

comment:6 Changed 6 years ago by C.Johnson

More details and another case where the ':not' selector fails:

 http://littlegreenfootballs.com/article/32453_Tech_Note-_JQuery_1.3_Released

comment:7 Changed 6 years ago by dchurch

I'm having a similar problem (infinite loop, same line), but it has nothing to do with the :not selector, so this may help in chasing down the bug. Given the following HTML structure:

<html>
 ...
 <body>
  <a></a>
 </body>
</html>

This query causes the infinite loop:

`$('div.someclass>span>a')`

Notably, these queries do NOT cause loops:

$('.someclass>span>a')
$('div>span>a')
$('div.someclass>body>a')
$('div.someclass>span>font')

It seems that the trouble comes when you have an initial selector (the A at the end) that does match at least one element, so checkSet isn't empty, then you step back to a selector that fails for ALL elements in checkSet (the span selector), so checkSet is now filled with false, then you step back one more level to a selector that has both a tag and a class specifier. preFilter.TAG() goes into an infinite loop trying to find an element to run isXML() on. I'm not sure where the fix for this should go, but that should be enough to track it down, hopefully.

Incidentally, I'm running Fx3.0.4 on Linux with Firebug enabled.

comment:8 Changed 6 years ago by john

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

Yeah, it was all about the preFilter.TAG logic - thanks for the pointer, dchurch. :not() was a red herring, but it's ok, since it should be fixed now:  http://github.com/jeresig/sizzle/commit/4a85526713de4e1b771dbe8b046d78dcec6da4b8

Will be merging the fix into jQuery soon.

Note: See TracTickets for help on using tickets.