[#25] Moved MethodBuilder property validation into MemberBuilderValidator
- Tests have not yet been movedclosure/master
parent
5e46298e39
commit
a91cb01998
|
@ -175,57 +175,12 @@ exports.buildProp = function( members, meta, name, value, keywords, base )
|
||||||
// TODO: We can improve performance by not scanning each one individually
|
// TODO: We can improve performance by not scanning each one individually
|
||||||
// every time this method is called
|
// every time this method is called
|
||||||
var prev_data = scanMembers( members, name, base ),
|
var prev_data = scanMembers( members, name, base ),
|
||||||
prev = ( prev_data ) ? prev_data.member : null;
|
prev = ( prev_data ) ? prev_data.member : null,
|
||||||
|
prev_keywords = ( prev ) ? prev[ 1 ] : null;
|
||||||
|
|
||||||
// disallow overriding methods with properties
|
this._validate.validateProperty(
|
||||||
if ( prev instanceof Function )
|
name, value, keywords, prev_data, prev_keywords
|
||||||
{
|
|
||||||
throw new TypeError(
|
|
||||||
"Cannot override method '" + name + "' with property"
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// do not allow overriding getters/setters
|
|
||||||
if ( prev_data && ( prev_data.get || prev_data.set ) )
|
|
||||||
{
|
|
||||||
throw TypeError(
|
|
||||||
"Cannot override getter/setter '" + name + "' with property"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not permit visibility de-escalation
|
|
||||||
if ( prev &&
|
|
||||||
( this._getVisibilityValue( prev[ 1 ] )
|
|
||||||
< this._getVisibilityValue( keywords )
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
throw TypeError(
|
|
||||||
"Cannot de-escalate visibility of property '" + name + "'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract properties do not make sense
|
|
||||||
if ( keywords[ 'abstract' ] )
|
|
||||||
{
|
|
||||||
throw TypeError(
|
|
||||||
"Property '" + name + "' cannot be declared as abstract"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( keywords[ 'static' ] && keywords[ 'const' ] )
|
|
||||||
{
|
|
||||||
throw TypeError(
|
|
||||||
"Static keyword cannot be used with const for property '" +
|
|
||||||
name + "'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// properties are inherently virtual
|
|
||||||
if ( keywords['virtual'] )
|
|
||||||
{
|
|
||||||
throw TypeError( "Cannot declare property '" + name + "' as virtual" );
|
|
||||||
}
|
|
||||||
|
|
||||||
getMemberVisibility( members, keywords )[ name ] = [ value, keywords ];
|
getMemberVisibility( members, keywords )[ name ] = [ value, keywords ];
|
||||||
};
|
};
|
||||||
|
|
|
@ -156,6 +156,80 @@ exports.prototype.validateMethod = function(
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a property declaration, ensuring that keywords are valid, overrides
|
||||||
|
* make sense, etc.
|
||||||
|
*
|
||||||
|
* Throws exception on validation failure
|
||||||
|
*
|
||||||
|
* @param {string} name method name
|
||||||
|
* @param {*} value method value
|
||||||
|
*
|
||||||
|
* @param {Object.<string,boolean>} keywords parsed keywords
|
||||||
|
*
|
||||||
|
* @param {Object} prev_data data of member being overridden
|
||||||
|
* @param {Object} prev_keywords keywords of member being overridden
|
||||||
|
*
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
exports.prototype.validateProperty = function(
|
||||||
|
name, value, keywords, prev_data, prev_keywords
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var prev = ( prev_data ) ? prev_data.member : null;
|
||||||
|
|
||||||
|
// disallow overriding methods with properties
|
||||||
|
if ( prev instanceof Function )
|
||||||
|
{
|
||||||
|
throw new TypeError(
|
||||||
|
"Cannot override method '" + name + "' with property"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not allow overriding getters/setters
|
||||||
|
if ( prev_data && ( prev_data.get || prev_data.set ) )
|
||||||
|
{
|
||||||
|
throw TypeError(
|
||||||
|
"Cannot override getter/setter '" + name + "' with property"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not permit visibility de-escalation
|
||||||
|
if ( prev &&
|
||||||
|
( this._getVisibilityValue( prev_keywords )
|
||||||
|
< this._getVisibilityValue( keywords )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw TypeError(
|
||||||
|
"Cannot de-escalate visibility of property '" + name + "'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// abstract properties do not make sense
|
||||||
|
if ( keywords[ 'abstract' ] )
|
||||||
|
{
|
||||||
|
throw TypeError(
|
||||||
|
"Property '" + name + "' cannot be declared as abstract"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( keywords[ 'static' ] && keywords[ 'const' ] )
|
||||||
|
{
|
||||||
|
throw TypeError(
|
||||||
|
"Static keyword cannot be used with const for property '" +
|
||||||
|
name + "'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// properties are inherently virtual
|
||||||
|
if ( keywords['virtual'] )
|
||||||
|
{
|
||||||
|
throw TypeError( "Cannot declare property '" + name + "' as virtual" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the visibility level as a numeric value, where 0 is public and 2 is
|
* Return the visibility level as a numeric value, where 0 is public and 2 is
|
||||||
* private
|
* private
|
||||||
|
|
|
@ -41,12 +41,11 @@ var common = require( './common' ),
|
||||||
|
|
||||||
mb_common.funcVal = null;
|
mb_common.funcVal = null;
|
||||||
mb_common.value = { baj: 'baz' };
|
mb_common.value = { baj: 'baz' };
|
||||||
mb_common.buildMember = builder.buildProp
|
|
||||||
|
|
||||||
// must wrap to call in proper context
|
// must wrap to call in proper context
|
||||||
var builder_method = function()
|
var builder_method = mb_common.buildMember = function()
|
||||||
{
|
{
|
||||||
builder.buildMethod.apply( builder, arguments );
|
builder.buildProp.apply( builder, arguments );
|
||||||
}
|
}
|
||||||
|
|
||||||
// do assertions common to all member builders
|
// do assertions common to all member builders
|
||||||
|
@ -94,6 +93,7 @@ mb_common.assertCommon();
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
mb_common.buildMember = builder_method;
|
||||||
mb_common.buildMemberQuick( { 'virtual': true } );
|
mb_common.buildMemberQuick( { 'virtual': true } );
|
||||||
}
|
}
|
||||||
catch ( e )
|
catch ( e )
|
||||||
|
|
Loading…
Reference in New Issue