Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What could cause this randomly appearing error inside jQuery itself?

I'm pounding my head against this. Once every 5-10 times I reload my app, I get a bizarre error originating inside jQuery. I try adding breakpoints inside the non-compressed version of jQuery to try to back out from the error, but Chrome never stops for them, instead always skipping ahead to the error.

I'm using jQuery 1.7.2, but this error also occurs in versions 1.7 and 1.6.1.

In my javascript app, I call this line of code:

this.element.find('.banner-btn')

Where this.element is a jQuery object. There is no reason this should cause a problem, and 9 times out of 10 there is no problem. But randomly something breaks, and then every time that line of code is called the result is some variant of this stack trace:

Uncaught TypeError: Cannot call method 'apply' of undefined
makeArrayjquery-1.7.2.js:4858
Sizzlejquery-1.7.2.js:5110
jQuery.fn.extend.findjquery-1.7.2.js:5432

In fact, any time after this breaks that I call $.fn.find I get this error. I have tried all kinds of things, I've been reading the jQuery source, and I can't get anywhere on this. Anybody have any idea where to go with nailing this down?

Update: further down the rabbit hole

I've chased this further into the jQuery library, and found where the error first pops up. Kind of.

To keep track of DOM traversal, jQuery uses the pushStack method. This is called in the jQuery.fn.find method, and is supposed to return a jQuery object. And it normally does -- but when something snaps inside jQuery, this function only returns a regular object, with no jQuery goodies. This causes an error down the line.

Okay, here is the first little bit of source for pushStack, defined on line 241 of jquery-1.7.2.js:

// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
if(window._debug_jQuery_pushStack) { debugger }
    // Build a new jQuery matched element set
    var ret = this.constructor();

// ---- the function continues, but this is enough for us ----

The bit where var ret = this.constructor(); is where the jQuery goodies are supposed to be added. In this case, they're not. Somehow this has been corrupted into a regular object, not jQuery. So now my question is: how do I find the cause of this corruption? A difficulty is that this only occurs once out of 10 or 20 times my application loads, and appears to be completely random.

like image 354
jpadvo Avatar asked Apr 20 '12 18:04

jpadvo


2 Answers

The problem is not in your code, but in Chrome itself -- see bug #125148. The current workaround is to change pushStack as follows:

pushStack: function( elems, name, selector ) {
    // Build a new jQuery matched element set
    var ret = this.constructor();

    // temporary workaround for chrome issue #125148
    // http://code.google.com/p/chromium/issues/detail?id=125148
    if (!(ret instanceof jQuery.fn.init)) {
        console.log("applying pushStack fix");
        ret = new jQuery.fn.init();
    }

    // ... snip ...

Also, see this related question.

like image 119
davidzarlengo Avatar answered Oct 01 '22 04:10

davidzarlengo


I don't think it's jquery, but something in your code, and jquery is responding to it. The culprit in my mind is the "undefined." Something's being manipulated by jquery (perhaps a var that's intended to be an array) inside your application that's causing this to happen. I've seen that recently when using backbone.js and using jquery for DOM operations. Turns out that occasionally, my app code was not properly setting a var and jquery threw an error when that happened.

So my advice is that if you know at least the general area within your sequence where the error is occurring, look at your app code and see if everything there is kosher; that all your vars are getting assigned. It's possible that there's an edge case where a var is not being assigned and it's a simple matter of placing a conditional around that area in case it's not.

like image 28
Brendan Delumpa Avatar answered Oct 01 '22 05:10

Brendan Delumpa