marionettejs / marionette.inspector

:mag: Marionette Inspector - Explore your App
http://goo.gl/Wo3pju
MIT License
170 stars 42 forks source link

Uncaught TypeError when using noConflict on libs #238

Open timsnadden opened 9 years ago

timsnadden commented 9 years ago

When I enabled the Marionette Inspector I get: Uncaught TypeError: Cannot read property 'View' of undefined

I suspect that this is caused by the fact that our application uses requirejs and loads jQuery, lodash, Backbone and Marionette with noConflict set and mappings in the requirejs config so that requiring 'backbone' (for example) pulls in 'backbone-private' for all modules except 'backbone-private'.

I'm wondering if Marionette Inspector will be able to handle this setup or whether I need to modify things to make the inspector work.

apply_now

jasonLaster commented 9 years ago

Thanks for the report. Mind running this locally and setting a breakpoint in patchDefine. You'll see the fund in the call stack and in the inspector agent source

https://github.com/marionettejs/marionette.inspector/blob/master/docs/developing_locally.md

timsnadden commented 9 years ago

Thanks for looking into this.

window.__agent.allPropertiesSet is called twice. The first time it succeeds and the second time it fails.

Before and after the error window.__agent.Backbone is defined.

When allPropertiesSet fails the properties argument is undefined.

I noticed the caveats around browserify and webpack. As I said, we are using requirejs but the libs are loaded with noConflict. I tried the following but still get the error.

require(['backbone', 'marionette'], function(Backbone, Marionette){
    if (window.__agent) {
        window.__agent.start(Backbone, Marionette);
    }
});
jasonLaster commented 9 years ago

@timsnadden - interesting finds. I'd like to know when the first call is made and when the second one is made. I assume you're looking inside of patchDefine and there's a ton of useful data available to you at that point wrt to the module loaded and other params to see who initiates the two calls.

I think you're onto something here that a lot of people will find who use noConflict.

timsnadden commented 9 years ago

When noConflict is called on Backbone previousBackbone is undefined. The error is thrown at this point:

root.Backbone = previousBackbone;

I was able to work around the issue by not calling noConflict for Backbone and Marionette.

previousbackbone

jasonLaster commented 9 years ago

hmm, is there an easy PR here that'd fix patchDefine?

timsnadden commented 9 years ago

As a first step I thought I would created the simplest Marionette app I could to demonstrate the problem. Without the inspector running this works as expected and shows 'Example content'. With the inspector running I get the Uncaught TypeError.

https://github.com/timsnadden/marionette-noconflict

jasonLaster commented 9 years ago

That's a huge step. Thanks!

Reproducing helps a lot.

vairav commented 9 years ago

I did the same as timsnadden, I commented out the Backbone.noConflict() part the Inspector loads.

But when the inspect load, the UI tab only shows "timestamp" with the console message "Marionette Inspector: Hmmm... couldn't find yo Backbone".

When digging into the issue, I found that window.__agent.patchedBackbone is undefined.

On typing "window.__agent.patchedBackbone" on the Console of DevTools, it return the backbone object:

Object {VERSION: "1.1.2", $: function, noConflict: function, emulateHTTP: false, emulateJSON: false…}

Not sure on how to proceed from here, so any help/advice/guidance would be great.

jasonLaster commented 9 years ago

What do you mean console of DevTools?

The next step is to break in patchDefine when either Mn or BB is defined and see what happens.

this will be where patchedBackbone gets set