Corrected virtual non-overridden trait method invocations
What a mouthful. And nightmare, having been away from the trait implementation for so long.protolib
parent
74b170d089
commit
779dbc37bc
11
lib/Trait.js
11
lib/Trait.js
|
@ -398,11 +398,12 @@ function createVirtProxy( acls, dfn )
|
||||||
? 'public'
|
? 'public'
|
||||||
: 'protected';
|
: 'protected';
|
||||||
|
|
||||||
var plen = acls.___$$methods$$[ vis ][ f ].__length;
|
var srcmethod = acls.___$$methods$$[ vis ][ f ],
|
||||||
|
plen = srcmethod.__length;
|
||||||
|
|
||||||
// this is the aforementioned proxy method; see the docblock for
|
// this is the aforementioned proxy method; see the docblock for
|
||||||
// more information
|
// more information
|
||||||
dfn[ vis + ' virtual override ' + f ] = ( function()
|
dfn[ vis + ' virtual override ' + f ] = ( function( f )
|
||||||
{
|
{
|
||||||
var retf = function()
|
var retf = function()
|
||||||
{
|
{
|
||||||
|
@ -422,16 +423,16 @@ function createVirtProxy( acls, dfn )
|
||||||
|
|
||||||
// this guy bypasses the above virtual override check, which is
|
// this guy bypasses the above virtual override check, which is
|
||||||
// necessary in certain cases to prevent infinte recursion
|
// necessary in certain cases to prevent infinte recursion
|
||||||
dfn[ vis + ' virtual __$$' + f ] = ( function( f )
|
dfn[ vis + ' virtual __$$' + f ] = ( function( method )
|
||||||
{
|
{
|
||||||
var retf = function()
|
var retf = function()
|
||||||
{
|
{
|
||||||
return this.___$$parent$$[ f ].apply( this, arguments );
|
return method.apply( this, arguments );
|
||||||
};
|
};
|
||||||
|
|
||||||
retf.__length = plen;
|
retf.__length = plen;
|
||||||
return retf;
|
return retf;
|
||||||
} )( f );
|
} )( srcmethod );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,52 @@ require( 'common' ).testCase(
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test unfortunately requires knowledge of implementation details
|
||||||
|
* to explain; it is a regression test covering a rather obnoxious bug,
|
||||||
|
* especially when the author was away from the implementation for a
|
||||||
|
* couple months.
|
||||||
|
*
|
||||||
|
* Proxying to an overridden protected method was not a problem because
|
||||||
|
* it proxies to the protected member object (PMO) which is passed into
|
||||||
|
* the ctor and, as is evident by its name, provides both the public and
|
||||||
|
* protected API. However, when not overridden, we fall back to having
|
||||||
|
* to invoke our original method, which is on our supertype---the
|
||||||
|
* abstract trait class. The problem there is that the stored supertype
|
||||||
|
* prototype provides only the public API.
|
||||||
|
*
|
||||||
|
* This test ensures that we properly access the protected API of our
|
||||||
|
* supertype. This problem existed before any general solution to this
|
||||||
|
* problem for all subtypes. We test public as well to produce a more
|
||||||
|
* general test case.
|
||||||
|
*
|
||||||
|
* The second part of this test is implicit---we're testing multiple
|
||||||
|
* virtual methods to ensure that they return distinct results, ensuring
|
||||||
|
* that we don't have any variable reassignment issues in the loop that
|
||||||
|
* generates the closures.
|
||||||
|
*/
|
||||||
|
'Properly invokes non-overridden virtual trait methods':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var expecteda = { a: true },
|
||||||
|
expectedb = { b: true };
|
||||||
|
|
||||||
|
var T = this.Sut(
|
||||||
|
{
|
||||||
|
pub: function() { return this.vpub(); },
|
||||||
|
prot: function() { return this.vprot(); },
|
||||||
|
|
||||||
|
'virtual public vpub': function() { return expecteda; },
|
||||||
|
'virtual protected vprot': function() { return expectedb; }
|
||||||
|
} );
|
||||||
|
|
||||||
|
var inst = this.Class.use( T ).extend( {} )();
|
||||||
|
|
||||||
|
this.assertStrictEqual( inst.pub(), expecteda );
|
||||||
|
this.assertStrictEqual( inst.prot(), expectedb );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the same concept as the non-virtual test found in the
|
* 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
|
* DefinitionTest case: since a trait is mixed into a class, if it
|
||||||
|
|
Loading…
Reference in New Issue