Success! Looks like we've fixed this one. According to our records the fix was applied for EXTJS-7251 in 4.1.4.
  1. #1
    Ext JS Premium Member
    Join Date
    Jun 2011
    Location
    Denmark
    Posts
    8
    Vote Rating
    0
    cdbruun is on a distinguished road

      0  

    Default Using treeviewdragdrop with Ext.tree.Panel causes IE8 to stack overflow

    Using treeviewdragdrop with Ext.tree.Panel causes IE8 to stack overflow


    All tree panels in my app that has the following viewConfig which
    has worked in all browsers up to an including 4.0.2a:

    Code:
    viewConfig: {
                plugins: {
                    ptype: 'treeviewdragdrop',               
                        enableDrop: false,
                        enableDrag: true,
                        dragGroup: 'DD_TSV'
               }
    }
    After upgrading to v4.1.1 I consistently get stackoverflow in IE8
    when I create a new Ext.tree.Panel like this:
    treePanel = new Ext.tree.Panel(self.config.treeConfig);
    - it works fine in IE9 and FF,


    Investigating the IE8 stack trace (using IE developer tools)
    I have discovered the problem:
    In the method Ext.tree.View.initComponent a new Ext.data.NodeStore
    is created (linie 109588 in v4.1.1):

    Code:
    me.store = new Ext.data.NodeStore({
                     treeStore: treeStore,
                     recursive: true,
                     rootVisible: me.rootVisible,
                     listeners: {
                             beforeexpand: me.onBeforeExpand,
                             expand: me.onExpand,
                             beforecollapse: me.onBeforeCollapse,
                             collapse: me.onCollapse,
                             write: me.onStorewrite,
                             datachanged: me.onStoreDataChanged,
                            scope: me
                    }
            });
    When constructing NodeStore the config object is cloned with Ext.Object.merge. This is a problem because it appears that listeners.scope contains the following circular reference:

    listeners.scope.plugins[0].initialConfig.cmp.plugins[0].initialConfig.cmp........ (stack overflow...)

    Why does this only happen in IE8 ?


    A workaround is to change the viewConfig to
    Code:
    viewConfig: {
            plugins: {
             ptype: 'treeviewdragdrop',               
                 enableDrop: false,
                 enableDrag: true,
                 dragGroup: 'DD_TSV',
                 nodeType: 'dummy',
                 cloneNode: function(bool) {
                     return (this);
                 }
            }
    }
    This will prevent the 'plugins' to be recursively cloned
    (see http://www.rahulsingla.com/blog/2011...lar-references)

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,004
    Vote Rating
    847
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Thanks for the report! I have opened a bug in our bug tracker.

  3. #3
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,898
    Vote Rating
    623
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    I can't reproduce this, is there anything I'm missing in this test case?

    Code:
    Ext.require('*');
    
    Ext.onReady(function() {
    
        var tree = new Ext.tree.Panel({
            width: 400,
            height: 200,
            renderTo: document.body,
            root: {
                text: 'Root',
                expanded: true,
                children: [{
                    text: 'A child',
                    leaf: true
                }]
            },
            viewConfig: {
                plugins: {
                    ptype: 'treeviewdragdrop',
                    enableDrop: false,
                    enableDrag: true,
                    dragGroup: 'DD_TSV'
                }
            }
        });
    
    });
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  4. #4
    Ext JS Premium Member
    Join Date
    Jun 2011
    Location
    Denmark
    Posts
    8
    Vote Rating
    0
    cdbruun is on a distinguished road

      0  

    Default


    I have a big js app so there is no easy way to cut out the trees in any meaningful way

    my config is
    Code:
    treeConfig : {
                            
                            collapsible: false,
                            animCollapse: false,
                            titleCollapse: true,
                            border: true,
                            rootVisible: true,
                            lines: true,
                            autoScroll: true,
                            animate: false,
                            stateful: false,
    //                        listeners: {
    //                            click: onClick
    //                        }
                            viewConfig: {
                                   plugins: {
                                  ptype: 'treeviewdragdrop',               
                                  enableDrop: false,
                                  enableDrag: true,
                                  dragGroup: 'DD_TSV',
                            nodeType: 'dummy', // IE8 specific
                              cloneNode: function(bool) {
                                  return (this);
                              }
                                   }
                               }
                        }
    I then programmatically insert the tree panel afterwards.

    My suspicion is that this is a timing issue where FF, IE9 and others are cloning the listeners.scope.plugins[0].initialConfig *before* the cmp is added. IE8 comes late and suffers when trying to clone cmp.

  5. #5
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,898
    Vote Rating
    623
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    You'll need to provide a test case, there's no issue in the examples with this, nor in the test case below:

    Code:
    Ext.require('*');
    
    Ext.onReady(function() {
    
        var ct = new Ext.container.Container({
            width: 400,
            height: 200,
            renderTo: document.body
        });
    
        setTimeout(function() {
            ct.add({
                xtype: 'treepanel',
                root: {
                    text: 'Root',
                    expanded: true,
                    children: [{
                        text: 'A child',
                        leaf: true
                    }]
                },
                viewConfig: {
                    plugins: {
                        ptype: 'treeviewdragdrop',
                        enableDrop: false,
                        enableDrag: true,
                        dragGroup: 'DD_TSV',
                        nodeType: 'dummy',
                        cloneNode: function(v) {
                            return this;
                        }
                    }
                }
            });
        }, 1000);
    
    });
    It may be something caused in your application code, but it's impossible to say without seeing it in action.
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  6. #6
    Ext JS Premium Member
    Join Date
    Jun 2011
    Location
    Denmark
    Posts
    8
    Vote Rating
    0
    cdbruun is on a distinguished road

      0  

    Default Plugins created in both Ext.AbstractComponent.constructor and initComponent

    Plugins created in both Ext.AbstractComponent.constructor and initComponent


    The problem arises because the plugins are constructed (in Ext.AbstractComponent.constructor) before the Ext.data.NodeStore is created in Ext.tree.View.initComponent

    From Ext.AbstractComponent.constructor (l.45253):
    Code:
            if (me.plugins) {
                me.plugins = me.constructPlugins();
            }
         
            if (!me.hasListeners) {
                me.hasListeners = new me.HasListeners();
            }
            me.initComponent();
    Then again in Ext.AbstractComponent.initComponent:
    Code:
              this.plugins = this.constructPlugins();
    It seems that you are constructing the plugins twice ?

    If I remove plugin construction from the constructor and rely on plugins being constructed in
    Ext.AbstractComponent.initComponent like this:
    Code:
          //  if (me.plugins) {
          //      me.plugins = me.constructPlugins();
          //  }
            if (!me.hasListeners) {
                me.hasListeners = new me.HasListeners();
            }
            me.initComponent();
    Then I do not experience any problems in IE8 or FF.

    I understand your request for a simple test case, but I am not sure it is possible to trigger the problem in a small program.
    My understanding og ExtJS is not deep enough to figure out if the is something asynchroneus in the object construction process that allows fast browsers to somehow complete initComponent before the plugins are constructed.

    Every time I attempt to debug object construction using FireBug then something breaks.

  7. #7
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,898
    Vote Rating
    623
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    A few things:

    1) It's calling the construction code twice, however it has guards around it to prevent it from initializing the plugin in a second time, in fact there are comments in the code:

    Code:
    initComponent: function () {
        // This is called again here to allow derived classes to add plugin configs to the
        // plugins array before calling down to this, the base initComponent.
        this.plugins = this.constructPlugins();
    
        // this will properly (ignore or) constrain the configured width/height to their
        // min/max values for consistency.
        this.setSize(this.width, this.height);
    }
    2) The same code appears in 4.0.7, constructPlugins is called in both the constructor & initComponent, so it's unlikely that this specific bit of the code is causing problems.

    3) I doubt there's anything to do with asynchronous processing here, the component construction code doesn't rely on any callbacks.

    Also, I'm not sure what this has to do with the nodeStore, it shouldn't really mess with the plugins.
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  8. #8
    Ext JS Premium Member
    Join Date
    Jun 2011
    Location
    Denmark
    Posts
    8
    Vote Rating
    0
    cdbruun is on a distinguished road

      0  

    Default


    ad 1) what I was suggesting was that perhaps the plugin initialization in the counstructor is not neccesary (leftovers from older versions perhaps)

    ad 2) The most recent version that does not show the stackoverflow problem in IE8 is v4.0.2a
    I have tested in v4.0.7, v4.1.0 and v4.1.1 and they all have the problem


    regarding the nodeStore:
    The stackoverflow happens in IE8 when creating the nodeStore. The problem is that after the plugins are constructed they contain a circular reference:plugin.initialConfig.cmp

    The config object used when creating the nodeStore contains the list of plugins through scope.plugins and therefore also has a circular reference

    The Ext.tree.View.initComponent calls
    The Ext.data.NodeStore.constructor which calls
    Ext.data.Store.constructor which as its very first line does:
    Code:
    config = Ext.Object.merge({}, config);
    Since the config given to NodeStore contains a circular reference this call terminates when the stack is full.

    In v4.0.2a the config in Ext.data.Store.constructor is created as:
    Code:
    config = config || {};
    In v4.0.7 the config in Ext.data.Store.constructor is created as:
    Code:
    config = Ext.Object.merge({}, config);
    The change from v4.0.2a to v4.0.7 is what causes the problem since in v4.0.2a you
    do not recursively clone the config object

  9. #9
    Ext JS Premium Member
    Join Date
    Jun 2011
    Location
    Denmark
    Posts
    8
    Vote Rating
    0
    cdbruun is on a distinguished road

      0  

    Default


    Just for the record:

    You should not include:
    Code:
    nodeType: 'dummy', 
     cloneNode: function(v) {          return this;  }
    When trying to reproduce the problem, since those settings are the workaround preventing
    the stackoverflow :-)

  10. #10
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,898
    Vote Rating
    623
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    No stackoverflow with/without that code.
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

Thread Participants: 2

Tags for this Thread