1
0
Fork 0

Can no longer override methods with getters/setters

closure/master
Mike Gerwitz 2011-06-12 01:07:43 -04:00
parent 6d31bf1084
commit 51e27334cd
2 changed files with 93 additions and 4 deletions

View File

@ -288,6 +288,8 @@ exports.buildProp = function( members, meta, name, value, keywords, base )
*/ */
exports.buildGetter = function( members, meta, name, value, keywords, base ) exports.buildGetter = function( members, meta, name, value, keywords, base )
{ {
validateGetterSetter( members, keywords, name, base );
Object.defineProperty( Object.defineProperty(
getMemberVisibility( members, keywords ), getMemberVisibility( members, keywords ),
name, name,
@ -320,6 +322,8 @@ exports.buildGetter = function( members, meta, name, value, keywords, base )
*/ */
exports.buildSetter = function( members, meta, name, value, keywords, base ) exports.buildSetter = function( members, meta, name, value, keywords, base )
{ {
validateGetterSetter( members, keywords, name, base );
Object.defineProperty( Object.defineProperty(
getMemberVisibility( members, keywords ), getMemberVisibility( members, keywords ),
name, name,
@ -334,6 +338,39 @@ exports.buildSetter = function( members, meta, name, value, keywords, base )
}; };
/**
* Performs common validations on getters/setters
*
* If a problem is found, an exception will be thrown.
*
* @param {{public: Object, protected: Object, private: Object}} members
*
* @param {Object.<string,boolean>} keywords parsed keywords
* @param {string} name getter/setter name
* @param {Object} base optional base to parse
*/
function validateGetterSetter( members, keywords, name, base )
{
var prev_data = scanMembers( members, name, base ),
prev = ( prev_data ) ? prev_data.member : null,
prev_keywords = ( prev && prev.___$$keywords$$ )
? prev.___$$keywords$$
: {}
;
if ( prev )
{
if ( typeof prev === 'function' )
{
throw TypeError(
"Cannot override method '" + name + "' with getter/setter"
);
}
}
}
/** /**
* Returns member prototype to use for the requested visibility * Returns member prototype to use for the requested visibility
* *

View File

@ -56,15 +56,41 @@ function setUp()
/** /**
* Partially applied function to quickly build getter from common test data * Partially applied function to quickly build getter from common test data
*/ */
function buildGetterSetterQuick( keywords, val ) function buildGetterSetterQuick( keywords, val, preserve_prior, use )
{ {
preserve_prior = !!preserve_prior;
use = ( use === undefined ) ? 0 : +use;
keywords = keywords || {}; keywords = keywords || {};
val = val || value; val = val || value;
setUp(); if ( !preserve_prior )
{
setUp();
}
buildGetter( members, meta, name, val, keywords ); if ( use == 0 || use == 1 )
buildSetter( members, meta, name, val, keywords ); {
buildGetter( members, meta, name, val, keywords );
}
if ( use == 0 || use == 2 )
{
buildSetter( members, meta, name, val, keywords );
}
}
function testEach( test )
{
test( 'getter', function( keywords, val, preserve )
{
buildGetterSetterQuick.call( this, keywords, val, preserve, 1 );
} );
test( 'setter', function( keywords, val, preserve )
{
buildGetterSetterQuick.call( this, keywords, val, preserve, 2 );
} );
} }
@ -176,3 +202,29 @@ function assertOnlyVisibility( vis, name, value, message )
} )(); } )();
/**
* Getters/setters should not be able to override methods, for the obvious
* reason that they are two different types and operate entirely differently. Go
* figure.
*/
testEach( function testCannotOverrideMethodWithGetterOrSetter( type, build )
{
setUp();
// method
members[ 'public' ][ name ] = function() {};
try
{
// attempt to override method with getter/setter (should fail)
build( { 'public': true }, null, true );
}
catch ( e )
{
return;
}
assert.fail( type + " should not be able to override methods");
} );