Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Suddenly my BackboneJS collections don't work in Chrome when the code is minified #2701

Closed
patrixd opened this Issue · 14 comments

7 participants

@patrixd

Suddenly my BackboneJS collections don't work in Chrome when the code is minified.
I have been searching for a bug in our code. But after fix some bugs, the application continue breaking when I use collections. If I change the collection for an array, the application works, but the next collection in the execution will cut again the execution.

I have to say that my application is really big. I have a model with lots of information and it has nested collections and models.

An example of a model with a collection, is usually the ones that fails.

    var MyCollection = Backbone.Collection.extend({ model: VinculacionesGrafo });

    var MyParentModel= Backbone.Model.extend({
        defaults: function () {
            return {
                mycollec: new MyCollection,
                finDeCarga: false
            };
        },

        initialize: function () {
            _.bindAll(this);
        },
        ....
        loadData: function () {
                var that = this;
                sendRequest({
                    type: "post",
                    url: ..,
                    dataType: "xml",
                    data: { ... },
                    success: this.success
                });
        },
        success: function(data) {
            model = new ChildModel;
            that.get("mycollec").add(model);
        }

It works allways in Firefox, Internet Explorer... But sometimes it fails in Chrome when the code is ready for production. I mean when the code is minified. At the beggining we thought it was a syncronoussly problem, but after change all collections by arrays it continues to fail in other collections that do not depends on loadding data. Allways the line with the error is something like: that.get("mycollec").add(model); And the stack is the next:

 TypeError: Cannot read property 'operaciones' of null
     at h.extend.get 
     at h.extend.set 
     at h.extend.add
     at g.Model.extend.addItem 
     at f.extend.cargarNodosIniciales

And addItem method is the next (not related with the text error):

addItem: function (item) {
     this.get("nodos").add(item);
},

Allways the error is related with some data that it is null, but the stack is not related with the error text. When the code is obfuscate and we detected it the first time, the error was something like that:

Uncaught TypeError: Cannot read property '1' of null 
    h.extend.get 
    h.extend.set 
    h.extend.add
    (anonymous function)
    t.each.t.forEach
    g.Model.extend.loadDataMercantiles 
    g.Model.extend.loadData 
    g.Model.extend.loadDataSuccess
    $.ajax.$.extend.success 
    m
    p.fireWith
    c
    (anonymous function)

The really strange thing is that when I change collections for arrays (in that code it will be mycollec: [] and push instead of add.) The bug does not appear anymore and the execution go on until it comes to another similar collection instruction.

I am really afraid. It is like backbone collections are broken. They works well sometimes and in the rest of the application they never fail. But It sames that section (that load lot of data and add lot of html) breaks backbone, or maybe is there a memory leak??

I am really lost. I am so sorry because the lack of the information the first time I wrote the question.

Thanks a lot in advance... I really need help

@jashkenas
Owner

This is a great example of an inappropriate use of the Backbone tickets. Please ask for help debugging your app on the mailing list, or in the IRC room (or StackOverflow, if you've narrowed it down).

@jashkenas jashkenas closed this
@patrixd

I'm so sorry, it was my mistake. I have written in Google group, I didn't know about it before.
https://groups.google.com/forum/#!topic/backbonejs/sD0gTI4bczc
Thanks

@cooldht

废话刚发现修仙传 废话刚发现修仙传

@philfreo

I typically wouldn't have posted a problem like this here either, but since there's a ticket open for it now... and I experienced the exact same issue (same error message, same Backbone.Collection#get line of code) as @patrixd

ONLY a problem in Chrome 28-29 with Backbone minified (for me using UglifyJS2). This appears to be a bug in Chrome 28 (stable) and 29 (beta) and the problem instantly goes away when you do any one of these things:

  • use the unminified Backbone source
  • use Chrome 30 (canary), Firefox, Safari, etc.
  • apply this (should be no-op but isn't) commit to your source before minifying: elasticsales@ba6e681

I couldn't find a related bug in V8 or Chromium bug trackers, but was content when figuring out both a working patch as well as that Chromium 30 fixes the issue. Possibly worth noting: for me the error only occurred on about 40% of pageloads, but that could have been due to the loading order of various ajax requests.

I also tried various options in UglifyJS -- but since it's seems to be a JS engine problem in Chrome/ium there's not much you can do.

@tgriesser
Collaborator

I'm fairly sure I hit the exact same issue @philfreo describes - minified code with uglify2 causing scripts to intermittently break or crash the tab in Chrome 28. I didn't have much time to spend on it, so currently I'm running the app with all uncompressed assets... I too looked for tickets in chrome and couldn't find anything that seemed to match, glad I wasn't the only one - I wonder if @paulirish has any ideas as to what might be happening here?

@jashkenas jashkenas reopened this
@vendethiel

isn't that a uglifyjs2 bug tho ?

@philfreo

isn't that a uglifyjs2 bug tho ?

I don't think so, since the minified code looked legit (seems logically equivalent to the source), runs fine in other browsers/versions, and the patch I referenced shouldn't logically affect the behavior but fixed the issue.

@patrixd

Thanks a lot @philfreo ! =) I will try that patch tomorrow and I will let you know if it fixed this issue. I have seen that patch and it is really weird, you are right it shouldn't logically affect. But if it works I will be happy. And I hope that the next version of Chrome fix this minified code issue.

@patrixd

I applied the patch before minifying and It works!! elasticsales@ba6e681

This error was an horror, we didn't notice it until the last week so we didn't imagine that it could be because the current version.

Thank you so much!

@paulirish

@tgriesser did you get a crashed tab from this behavior? If so it'd be super helpful to get a reference to the Crash ID.
http://www.chromium.org/for-testers/bug-reporting-guidelines/reporting-crash-bug

This is going to be a little tricky without a smaller repro. @philfreo can you start a ticket on the v8 tracker with the before and after demos.. And hopefully we can start to widdle down the issue. Meanwhile the v8 team might have come across this already..

@patrixd

Hi @paulirish, in my case the Chrome tab has never crashed. But I have enabled the crash reports and I will be able to get a crash ID in the case the crash happens. I only got a javascript error and its stack.

Uncaught TypeError: Cannot read property '1' of null
h.extend.get
h.extend.set
h.extend.add
...

I can only suggest you to see the code that fix the problem elasticsales@ba6e681

If there is anything I can do to help, please let me know.

@paulirish
@patrixd

I used the minified version of backbone.

get: function (t) { if (t == null) return void 0; return this._byId[t.id != null ? t.id : t.cid || t] }

I replaced it by the next and It works:

get: function (t) { if (t == null) return void 0; var id = t.id; return this._byId[id != null ? id : t.cid || t] }

After apply google closure (with a compilation level of SIMPLE_OPTIMIZATIONS, join the code generated by require r.js, with other libraries) I compared the two versions of the final code, the one that I use in the app.

So the main difference is the next (this code does not work arbitrary in chrome), the other differences are the name of the variables

get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a.cid||a]}

The next function allways works:

get:function(a){if(null!=a){var b=a.id;return this._byId[null!=b?b:a.cid||a]}}

I hope it helps you.

I don't have installed chrome 30, I'm going to install it just now. But @philfreo said that it works fine there. I'm going to try my code anyway.

Thanks

@patrixd

I just tried the app in chrome 30. The two versions worked correctly as @philfreo said.
Maybe you have already fixed that problem.

Can I do anything else to help?

@jashkenas jashkenas closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.