diff --git a/TODO b/TODO index f030cee..deafa05 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ [ target: 0.1.0 ] Misc - Class module is becoming too large; refactor - - Disallow member redeclaration in definition - Permit binding on class methods - Move tests to directly test propobj - Was never done after refactoring. It's tested as a consequence of being diff --git a/lib/class.js b/lib/class.js index d352f0a..a8a1e08 100644 --- a/lib/class.js +++ b/lib/class.js @@ -444,6 +444,7 @@ var extend = ( function( extending ) properties = {}, prop_init = member_builder.initMembers(), members = member_builder.initMembers( prototype ), + defs = {}, abstract_methods = util.clone( getMeta( base ).abstractMethods ) @@ -480,6 +481,19 @@ var extend = ( function( extending ) "__initProps is a reserved method" ); } + + // if a member was defined multiple times in the same class + // declaration, throw an error + if ( hasOwn.call( defs, name ) ) + { + throw Error( + "Cannot redefine method '" + name + "' in same declaration" + ); + } + + // keep track of the definitions (only during class declaration) + // to catch duplicates + defs[ name ] = 1; }, property: function( name, value, keywords ) diff --git a/test/test-class-extend.js b/test/test-class-extend.js index f60df03..29aa3fd 100644 --- a/test/test-class-extend.js +++ b/test/test-class-extend.js @@ -311,3 +311,40 @@ for ( var i = 0; i < class_count; i++ ) ); } )(); + +/** + * In ease.js's initial design, keywords were not included. This meant that + * duplicate member definitions were not possible - it'd throw a parse error. + * However, with keywords, it is now possible to redeclare a member with the + * same name in the same class definition. Since this doesn't make much sense, + * we must disallow it. + */ +( function testCannotProvideDuplicateMemberDefintions() +{ + assert.throws( function() + { + Class( + { + // declare as protected first so that we won't get a visibility + // de-escalation error with the below re-definition + 'protected foo': '', + + // should fail; redefinition + 'public foo': '', + } ); + }, Error, "Cannot redeclare property in same class definition" ); + + assert.throws( function() + { + Class( + { + // declare as protected first so that we won't get a visibility + // de-escalation error with the below re-definition + 'protected foo': function() {}, + + // should fail; redefinition + 'public foo': function() {}, + } ); + }, Error, "Cannot redeclare method in same class definition" ); +} )(); +