Trait method return value implementation correction and testing
parent
6473cf35ae
commit
c8023cb382
|
@ -236,7 +236,7 @@ function createVirtProxy( acls, dfn )
|
||||||
{
|
{
|
||||||
return function()
|
return function()
|
||||||
{
|
{
|
||||||
this.___$$parent$$[ f ].apply( this, arguments );
|
return this.___$$parent$$[ f ].apply( this, arguments );
|
||||||
};
|
};
|
||||||
} )( f );
|
} )( f );
|
||||||
}
|
}
|
||||||
|
@ -328,7 +328,6 @@ function mixMethods( src, dest, vis, iname )
|
||||||
}
|
}
|
||||||
|
|
||||||
// if non-virtual, a normal proxy should do
|
// if non-virtual, a normal proxy should do
|
||||||
// TODO: test return value; see below
|
|
||||||
if ( !( keywords['virtual'] ) )
|
if ( !( keywords['virtual'] ) )
|
||||||
{
|
{
|
||||||
dest[ pname ] = iname;
|
dest[ pname ] = iname;
|
||||||
|
@ -350,9 +349,8 @@ function mixMethods( src, dest, vis, iname )
|
||||||
// additional overhead or confusion
|
// additional overhead or confusion
|
||||||
var ret = pdest[ '__$$' + f ].apply( pdest, arguments );
|
var ret = pdest[ '__$$' + f ].apply( pdest, arguments );
|
||||||
|
|
||||||
// TODO: test return value
|
|
||||||
// if the trait returns itself, return us instead
|
// if the trait returns itself, return us instead
|
||||||
return ( ret === iname )
|
return ( ret === pdest )
|
||||||
? this
|
? this
|
||||||
: ret;
|
: ret;
|
||||||
};
|
};
|
||||||
|
|
|
@ -280,4 +280,28 @@ require( 'common' ).testCase(
|
||||||
this.Class( 'Named' ).use( T ).extend( {} )().foo();
|
this.Class( 'Named' ).use( T ).extend( {} )().foo();
|
||||||
this.assertOk( called );
|
this.assertOk( called );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a trait is mixed into a class, it acts as though it is part of
|
||||||
|
* that class. Therefore, it should stand to reason that, when a mixed
|
||||||
|
* in method returns `this', it should actually return the instance of
|
||||||
|
* the class that it is mixed into (in the case of this test, its
|
||||||
|
* private member object, since that's our context when invoking the
|
||||||
|
* trait method).
|
||||||
|
*/
|
||||||
|
'Trait method that returns self will return containing class':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var _self = this,
|
||||||
|
T = this.Sut( { foo: function() { return this; } } );
|
||||||
|
|
||||||
|
this.Class.use( T ).extend(
|
||||||
|
{
|
||||||
|
go: function()
|
||||||
|
{
|
||||||
|
_self.assertStrictEqual( this, this.foo() );
|
||||||
|
},
|
||||||
|
} )().go();
|
||||||
|
},
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -188,4 +188,117 @@ require( 'common' ).testCase(
|
||||||
C().doFoo();
|
C().doFoo();
|
||||||
this.assertOk( called );
|
this.assertOk( called );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the same concept as the non-virtual test found in the
|
||||||
|
* DefinitionTest case: since a trait is mixed into a class, if it
|
||||||
|
* returns itself, then it should in actuality return the instance of
|
||||||
|
* the class it is mixed into.
|
||||||
|
*/
|
||||||
|
'Virtual trait method returning self returns class instance':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
var T = this.Sut( { 'virtual foo': function() { return this; } } );
|
||||||
|
|
||||||
|
this.Class.use( T ).extend(
|
||||||
|
{
|
||||||
|
go: function()
|
||||||
|
{
|
||||||
|
_self.assertStrictEqual( this, this.foo() );
|
||||||
|
},
|
||||||
|
} )().go();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same concept as the above test case, but ensures that invoking the
|
||||||
|
* super method does not screw anything up.
|
||||||
|
*/
|
||||||
|
'Overridden virtual trait method returning self returns class instance':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
var T = this.Sut( { 'virtual foo': function() { return this; } } );
|
||||||
|
|
||||||
|
this.Class.use( T ).extend(
|
||||||
|
{
|
||||||
|
'override foo': function()
|
||||||
|
{
|
||||||
|
return this.__super();
|
||||||
|
},
|
||||||
|
|
||||||
|
go: function()
|
||||||
|
{
|
||||||
|
_self.assertStrictEqual( this, this.foo() );
|
||||||
|
},
|
||||||
|
} )().go();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a trait method is overridden, ensure that the data are properly
|
||||||
|
* proxied back to the caller. This differs from the above tests, which
|
||||||
|
* just make sure that the method is actually overridden and invoked.
|
||||||
|
*/
|
||||||
|
'Data are properly returned from trait override super call': function()
|
||||||
|
{
|
||||||
|
var _self = this,
|
||||||
|
expected = {};
|
||||||
|
|
||||||
|
var T = this.Sut(
|
||||||
|
{
|
||||||
|
'virtual foo': function() { return expected; }
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.Class.use( T ).extend(
|
||||||
|
{
|
||||||
|
'override foo': function()
|
||||||
|
{
|
||||||
|
_self.assertStrictEqual( expected, this.__super() );
|
||||||
|
},
|
||||||
|
} )().foo();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a trait method is overridden by the class that it is mixed into,
|
||||||
|
* and the super method is called, then the trait method should execute
|
||||||
|
* within the private member context of the trait itself (as if it were
|
||||||
|
* never overridden). Some kinky stuff would have to be going on (at
|
||||||
|
* least in the implementation at the time this was written) for this
|
||||||
|
* test to fail, but let's be on the safe side.
|
||||||
|
*/
|
||||||
|
'Super trait method overrided in class executed within private context':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var expected = {};
|
||||||
|
|
||||||
|
var T = this.Sut(
|
||||||
|
{
|
||||||
|
'virtual foo': function()
|
||||||
|
{
|
||||||
|
// should succeed
|
||||||
|
return this.priv();
|
||||||
|
},
|
||||||
|
|
||||||
|
'private priv': function()
|
||||||
|
{
|
||||||
|
return expected;
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.assertStrictEqual( expected,
|
||||||
|
this.Class.use( T ).extend(
|
||||||
|
{
|
||||||
|
'override virtual foo': function()
|
||||||
|
{
|
||||||
|
return this.__super();
|
||||||
|
},
|
||||||
|
} )().foo()
|
||||||
|
);
|
||||||
|
},
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in New Issue