Protected trait methods are now mixed in
parent
3724b1bc0d
commit
e44ac3190b
47
lib/Trait.js
47
lib/Trait.js
|
@ -38,7 +38,7 @@ Trait.extend = function( dfn )
|
|||
// we need at least one abstract member in order to declare a class as
|
||||
// abstract (in this case, our trait class), so let's create a dummy one
|
||||
// just in case DFN does not contain any abstract members itself
|
||||
dfn[ 'abstract protected __$$trait$$' ] = [];
|
||||
dfn[ 'abstract protected ___$$trait$$' ] = [];
|
||||
|
||||
function TraitType()
|
||||
{
|
||||
|
@ -88,7 +88,7 @@ function createConcrete( acls )
|
|||
{
|
||||
// start by providing a concrete implementation for our dummy method
|
||||
var dfn = {
|
||||
'protected __$$trait$$': function() {},
|
||||
'protected ___$$trait$$': function() {},
|
||||
};
|
||||
|
||||
// TODO: everything else
|
||||
|
@ -111,44 +111,59 @@ function mixin( trait, dfn )
|
|||
{
|
||||
// the abstract class hidden within the trait
|
||||
var acls = trait.__acls,
|
||||
methods = acls.___$$methods$$,
|
||||
pub = methods['public'];
|
||||
methods = acls.___$$methods$$;
|
||||
|
||||
// retrieve the private member name that will contain this trait object
|
||||
var iname = addTraitInst( trait.__ccls, dfn );
|
||||
|
||||
// TODO: protected; ignore abstract
|
||||
for ( var f in pub )
|
||||
mixMethods( methods['public'], dfn, 'public', iname );
|
||||
mixMethods( methods['protected'], dfn, 'protected', iname );
|
||||
|
||||
return dfn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mix methods from SRC into DEST using proxies
|
||||
*
|
||||
* @param {Object} src visibility object to scavenge from
|
||||
* @param {Object} dest destination definition object
|
||||
* @param {string} vis visibility modifier
|
||||
* @param {string} ianem proxy destination (trait instance)
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
function mixMethods( src, dest, vis, iname )
|
||||
{
|
||||
// TODO: ignore abstract
|
||||
for ( var f in src )
|
||||
{
|
||||
if ( !( Object.hasOwnProperty.call( pub, f ) ) )
|
||||
if ( !( Object.hasOwnProperty.call( src, f ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: this is a kluge; we'll use proper reflection eventually,
|
||||
// but for now, this is how we determine if this is an actual public
|
||||
// method vs. something that just happens to be on the public
|
||||
// visibility object
|
||||
if ( !( pub[ f ].___$$keywords$$ ) )
|
||||
// but for now, this is how we determine if this is an actual method
|
||||
// vs. something that just happens to be on the visibility object
|
||||
if ( !( src[ f ].___$$keywords$$ ) || f === '___$$trait$$' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var pname = 'public proxy ' + f;
|
||||
var pname = vis + ' proxy ' + f;
|
||||
|
||||
// if we have already set up a proxy for a field of this name, then
|
||||
// multiple traits have defined the same concrete member
|
||||
if ( dfn[ pname ] !== undefined )
|
||||
if ( dest[ pname ] !== undefined )
|
||||
{
|
||||
// TODO: between what traits?
|
||||
throw Error( "Trait member conflict: `" + f + "'" );
|
||||
}
|
||||
|
||||
// proxy this method to what will be the encapsulated trait object
|
||||
dfn[ pname ] = iname;
|
||||
dest[ pname ] = iname;
|
||||
}
|
||||
|
||||
return dfn;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -45,18 +45,17 @@ require( 'common' ).testCase(
|
|||
],
|
||||
|
||||
// should (at least for the time being) be picked up by existing
|
||||
// class error checks
|
||||
// class error checks; TODO: but let's provide trait-specific
|
||||
// error messages to avoid frustration and infuriation
|
||||
[ 'foo', "varying keywords; same visibility",
|
||||
{ 'virtual public foo': function() {} },
|
||||
{ 'public virtual foo': function() {} },
|
||||
],
|
||||
|
||||
/* TODO
|
||||
[ 'foo', "different visibility",
|
||||
{ 'public foo': function() {} },
|
||||
{ 'protected foo': function() {} },
|
||||
],
|
||||
*/
|
||||
];
|
||||
},
|
||||
|
||||
|
@ -234,7 +233,7 @@ require( 'common' ).testCase(
|
|||
// caused the error
|
||||
this.assertOk(
|
||||
e.message.match( '\\b' + fname + '\\b' ),
|
||||
"Missing field name"
|
||||
"Error message missing field name: " + e.message
|
||||
);
|
||||
|
||||
// TODO: we can also make less people hate us if we include the
|
||||
|
|
Loading…
Reference in New Issue