Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: callParent can be broken under two scenarios.

    Wait! Looks like we don't have enough information to add this to bug database. Please follow this template bug format.
  1. #1
    Sencha Premium Member
    Join Date
    Sep 2010
    Posts
    100
    Vote Rating
    5
      0  

    Default callParent can be broken under two scenarios.

    [4.*] There are multiple cases that callParent doesn't handle. To be honest I don't think it should have to handle both of these scenarios but it should allow for overrides to be shared and work properly. We need to be able to define an override once and have it get applied to multiple classes cloning methods or sharing method instances mess up callParent calls.


    REQUIRED INFORMATION
    Ext version tested:

    • > Ext 4.*
    Test Case:
    Scenario 1:
    Have an override share a function that has a callParent
    Code:
    //Sharing the same method messes up the $previous property
    Code:
    var initComponent = function() {
            console.log(1)
            this.callParent();
    }
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
        initComponent: initComponent
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
         initComponent: initComponent
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
         initComponent: initComponent
    })

    >new Ext.Component()

    >1


    Scenario 2 don't share the method but clone it instead


    Code:
    //Cloning the method makes callParent not handle the caller property
    // and in turn callParent thinks $previous is undefined even though it isn't
    Code:
    var initComponent = function() {
            console.log(1)
            this.callParent();
    }
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
        initComponent: Ext.clone(initComponent)
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
         initComponent: Ext.clone(initComponent)
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
         initComponent: Ext.clone(initComponent)
    })

    >new Ext.Component()

    >1


    Working code:
    Code:
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
        initComponent: function() {
            console.log(1)
            this.callParent();
        }
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
        initComponent: function() {
            console.log(1)
            this.callParent();
        }
    })
    
    
    Ext.define('Ext.overrides.Component',{
        override: 'Ext.Component',
        initComponent: Ext.clone(function() {
            console.log(1)
            this.callParent();
        })
    })

    >new Ext.Component()

    >1

    >1

    >1




  2. #2
    Sencha - Sr Software Engineer mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    39,553
    Vote Rating
    1272
      0  

    Default

    What is the use case for sharing a single initComponent method?
    Mitchell Simoens @LikelyMitch
    Sencha Inc, Senior Software Engineer
    ________________
    Learn BBCode and use it! Checkout the CODE tag!

    Check out my GitHub, lots of nice things for Ext JS and Sencha Touch
    https://github.com/mitchellsimoens

  3. #3
    Sencha Premium User
    Join Date
    Nov 2010
    Location
    Chicago
    Posts
    1,932
    Vote Rating
    548
      0  

    Default

    Quote Originally Posted by mitchellsimoens View Post
    What is the use case for sharing a single initComponent method?
    Also, cloning a function returns the same function, so what's the point of cloning?


    Code:
    var fn = function(){};
    fn === Ext.clone(fn); // true

  4. #4
    Sencha Premium Member
    Join Date
    Sep 2010
    Posts
    100
    Vote Rating
    5
      0  

    Default

    Use case: We have a 200+ line long override that we want apply it to Ext.form.field.Text, Ext.form.CheckboxGroup, one of our custom fields (that doesn't extend from Text of Checkbox group) and any other custom field in the future if need be.

  5. #5
    Sencha Premium Member
    Join Date
    Sep 2010
    Posts
    100
    Vote Rating
    5
      0  

    Default

    Quote Originally Posted by LesJ View Post
    Also, cloning a function returns the same function, so what's the point of cloning?


    Code:
    var fn = function(){};
    fn === Ext.clone(fn); // true
    There is a problem with shared instances hence the cloning. A cloned object should not return the same instance. For the example I assumed that Ext.clone(fn) would be equivalent to Ext.Function.clone(fn) apparently it is not. It is still a problem though. Excuse my formatting:

    Code:
    var initComponent = function() {        console.log(1)        this.callParent();}Ext.define('Ext.overrides.Component',{    override: 'Ext.Component',    initComponent: Ext.Function.clone(initComponent)})Ext.define('Ext.overrides.Component',{    override: 'Ext.Component',     initComponent: Ext.Function.clone(initComponent)})Ext.define('Ext.overrides.Component',{    override: 'Ext.Component',     initComponent: Ext.Function.clone(initComponent)})
    new Ext.Component()
    >1

    Code:
    Ext.Function.clone(Ext.emptyFn) === Ext.emptyFn
    > false

  6. #6
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    18,587
    Vote Rating
    873
      0  

    Default

    I'm not really sure I see the point of your test case.

    You're:
    1) Defining the same override name 3 times
    2) You're overriding the same function, with the same function reference 3 times

    I realise it may be for the sake of demonstrating something, but in it's current form it's quite confusing as to what you're trying to achieve.
    Evan Trimboli
    Twitter - @evantrimboli

  7. #7
    Sencha Premium Member
    Join Date
    Sep 2010
    Posts
    100
    Vote Rating
    5
      0  

    Default

    Quote Originally Posted by evant View Post
    I'm not really sure I see the point of your test case.

    You're:
    1) Defining the same override name 3 times
    2) You're overriding the same function, with the same function reference 3 times

    I realise it may be for the sake of demonstrating something, but in it's current form it's quite confusing as to what you're trying to achieve.
    What is confusing about the test case? The problem is titled there are two scenarios which callParent can be broken. The test case is demonstrating that callParent doesn't work in all of those scenarios. If it did work it would >1 >1 >1 would be logged to the console but only >1 does. It actually doesn't matter if is the same override, all it needs to be broken are is to override a method that has a callParent in it with a cloned function or the same instance.

    Quote Originally Posted by plleeuwm View Post
    Use case: We have a 200+ line long override that we want apply it to Ext.form.field.Text, Ext.form.CheckboxGroup, one of our custom fields (that doesn't extend from Text of Checkbox group) and any other custom field in the future if need be.

  8. #8
    Sencha Premium Member
    Join Date
    Sep 2010
    Posts
    100
    Vote Rating
    5
      0  

    Default

    What more info is needed? I've provided use cases, expected results and ways to reproduce the problem and this obviously isn't a browser or OS specific issue.

    I can provide two more use cases related to the same problems.

    This works:

    Code:
    Ext.define('MyObject', {
        log: function() {
            console.log(0);
        }
    });
    
    
    Ext.override(MyObject, {
        log:function(num) {
            console.log(1);
            this.callParent();
        }
    });
    
    
    Ext.override(MyObject, {
        log: (function() {
            return function() {
                console.log(2);
                this.callParent();
            }
        })()
    });
    new MyObject().log()
    > 2
    > 1
    > 0

    These don't:

    Code:
    Ext.define('MyObject', {
        log: function() {
            console.log(0);
        }
    });
    
    
    Ext.override(MyObject, {
        log:function(num) {
            console.log(1);
            this.callParent();
        }
    });
    
    
    Ext.override(MyObject, {
        log:Ext.Function.createSequence(function(){
            console.log(2);
        }, function(){
            this.callParent();
        })
    });
    Code:
    Ext.define('MyObject', {
        log: function() {
            console.log(0);
        }
    });
    
    
    Ext.override(MyObject, {
        log:function(num) {
            console.log(1);
            this.callParent();
        }
    });
    
    
    
    
    Ext.override(MyObject, {
        log: Ext.pass(function(num) {
            console.log(num);
            this.callParent();
        }, [2])
    });
    new MyObject().log()
    >2
    >Error: this.callParent() was called but there's no such method (log) found in the parent class (Ext.Base)

  9. #9
    Sencha Premium User mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    3,078
    Vote Rating
    184
      0  

    Default

    By adding that extra wrapping function, you're preventing the callParent method from functioning correctly. Is there any use case for your construct?

    This is what you end up getting:

    Code:
    MyObject.override({
        log: function(num) {
            function inner (num) {
                console.log(num);
                this.callParent();
            }
            inner.apply(this, arguments);
        }
    });

  10. #10
    Sencha Premium User
    Join Date
    Nov 2010
    Location
    Chicago
    Posts
    1,932
    Vote Rating
    548
      0  

    Default

    See if callSuper would be a better fit instead of callParent.

    I
    'd stay away from using the 'pass' and 'createSequence' functions to modify the methods.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •