From 51e27334cd054dc6fbfc3abf62888812ec58531a Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Sun, 12 Jun 2011 01:07:43 -0400 Subject: [PATCH] Can no longer override methods with getters/setters --- lib/member_builder.js | 37 +++++++++++++++ test/test-member_builder-gettersetter.js | 60 ++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/lib/member_builder.js b/lib/member_builder.js index 7a071c3..cab1729 100644 --- a/lib/member_builder.js +++ b/lib/member_builder.js @@ -288,6 +288,8 @@ exports.buildProp = function( members, meta, name, value, keywords, base ) */ exports.buildGetter = function( members, meta, name, value, keywords, base ) { + validateGetterSetter( members, keywords, name, base ); + Object.defineProperty( getMemberVisibility( members, keywords ), name, @@ -320,6 +322,8 @@ exports.buildGetter = function( members, meta, name, value, keywords, base ) */ exports.buildSetter = function( members, meta, name, value, keywords, base ) { + validateGetterSetter( members, keywords, name, base ); + Object.defineProperty( getMemberVisibility( members, keywords ), 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.} 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 * diff --git a/test/test-member_builder-gettersetter.js b/test/test-member_builder-gettersetter.js index 6a3ece8..8d1d966 100644 --- a/test/test-member_builder-gettersetter.js +++ b/test/test-member_builder-gettersetter.js @@ -56,15 +56,41 @@ function setUp() /** * 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 || {}; val = val || value; - setUp(); + if ( !preserve_prior ) + { + setUp(); + } - buildGetter( members, meta, name, val, keywords ); - buildSetter( members, meta, name, val, keywords ); + if ( use == 0 || use == 1 ) + { + 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"); +} ); +