diff --git a/lib/MemberBuilder.js b/lib/MemberBuilder.js index 26ed534..309d4c6 100644 --- a/lib/MemberBuilder.js +++ b/lib/MemberBuilder.js @@ -210,7 +210,7 @@ exports.buildGetter = function( members, meta, name, value, keywords, base ) var prev_data = scanMembers( members, name, base ); this._validate.validateGetterSetter( - name, members, keywords, base, prev_data + name, keywords, prev_data ); Object.defineProperty( @@ -250,7 +250,7 @@ exports.buildSetter = function( members, meta, name, value, keywords, base ) var prev_data = scanMembers( members, name, base ); this._validate.validateGetterSetter( - name, members, keywords, base, prev_data + name, keywords, prev_data ); this._validate.validateGetterSetter( name, members, keywords, base ); diff --git a/lib/MemberBuilderValidator.js b/lib/MemberBuilderValidator.js index d184f27..3682220 100644 --- a/lib/MemberBuilderValidator.js +++ b/lib/MemberBuilderValidator.js @@ -237,16 +237,12 @@ exports.prototype.validateProperty = function( * If a problem is found, an exception will be thrown. * * @param {string} name getter/setter name - * - * @param {{public: Object, protected: Object, private: Object}} members - * * @param {Object.} keywords parsed keywords - * @param {Object} base optional base to parse * * @return {undefined} */ exports.prototype.validateGetterSetter = function( - name, members, keywords, base, prev_data + name, keywords, prev_data ) { var prev = ( prev_data ) ? prev_data.member : null, diff --git a/test/MemberBuilderValidator/GetterSetterTest.js b/test/MemberBuilderValidator/GetterSetterTest.js new file mode 100644 index 0000000..943447c --- /dev/null +++ b/test/MemberBuilderValidator/GetterSetterTest.js @@ -0,0 +1,79 @@ +/** + * Tests member builder validation rules for getters/setters + * + * These tests can be run in a pre-ES5 environment since they do not deal with + * actual getters/setters; they deal only with the data associated with them. + * + * Copyright (C) 2010 Mike Gerwitz + * + * This file is part of ease.js. + * + * ease.js is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * @author Mike Gerwitz + * @package test + */ + +var shared = require( __dirname + '/inc-common' ); + +require( 'common' ).testCase( +{ + caseSetUp: function() + { + this.quickFailureTest = shared.quickFailureTest; + }, + + + setUp: function() + { + this.sut = this.require( 'MemberBuilderValidator' )(); + }, + + + /** + * 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. + */ + 'Cannot override method with getter or setter': function() + { + var name = 'foo', + _self = this; + + // getters and setters share the same call, so we don't need two + // separate tests + this.quickFailureTest( name, 'method', function() + { + _self.sut.validateGetterSetter( + name, {}, { member: function() {} } + ); + } ); + }, + + + 'Cannot override property with getter or setter': function() + { + var name = 'foo', + _self = this; + + // getters and setters share the same call, so we don't need two + // separate tests + this.quickFailureTest( name, 'method', function() + { + _self.sut.validateGetterSetter( + name, {}, { member: 'foo' } + ); + } ); + }, +} ); diff --git a/test/test-member_builder-gettersetter.js b/test/test-member_builder-gettersetter.js deleted file mode 100644 index fa93f67..0000000 --- a/test/test-member_builder-gettersetter.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Tests getter/setter builder - * - * Copyright (C) 2010 Mike Gerwitz - * - * This file is part of ease.js. - * - * ease.js is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * @author Mike Gerwitz - * @package test - */ - -var common = require( './common' ), - assert = require( 'assert' ), - util = common.require( 'util' ), - - builder = common.require( 'MemberBuilder' )(), - - buildGetter = function() - { - builder.buildGetter.apply( builder, arguments ); - }, - - buildSetter = function() - { - builder.buildSetter.apply( builder, arguments ); - }, - - // member visibility types are quoted because they are reserved keywords - members = {}, - meta = {}, - - // stub values - name = 'foo', - value = function() {} -; - - -// no need to test getters/setters in browsers that do not support them -if ( util.definePropertyFallback() ) -{ - return; -} - - -function setUp() -{ - // clear out the members for a fresh start - members = { 'public': {}, 'protected': {}, 'private': {} }; -} - - -/** - * Partially applied function to quickly build getter from common test data - */ -function buildGetterSetterQuick( keywords, val, preserve_prior, use ) -{ - preserve_prior = !!preserve_prior; - use = ( use === undefined ) ? 0 : +use; - - keywords = keywords || {}; - val = val || value; - - if ( !preserve_prior ) - { - setUp(); - } - - 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 ); - } ); -} - - -( function testThrowsTypeErrorIfMultipleVisibilityKeywordsAreGiven() -{ - assert.throws( function() - { - buildGetterSetterQuick( { - 'public': true, - 'protected': true, - } ); - }, TypeError, "Cannot specify multiple visibility keywords (0)" ); - - assert.throws( function() - { - buildGetterSetterQuick( { - 'public': true, - 'private': true, - } ); - }, TypeError, "Cannot specify multiple visibility keywords (1)" ); - - assert.throws( function() - { - buildGetterSetterQuick( { - 'protected': true, - 'private': true, - } ); - }, TypeError, "Cannot specify multiple visibility keywords (2)" ); - -} )(); - - -/** - * 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 ) - { - assert.ok( e.message.search( name ) !== -1, - "Method override error message should contain " + type + " name" - ); - return; - } - - assert.fail( type + " should not be able to override methods"); -} ); - - -/** - * Getters/setters should not be able to override properties. While, at first, - * this concept may seem odd, keep in mind that the parent would likely not - * expect a subtype to be able to override property assignments. This could open - * up holes to exploit the parent class. - */ -testEach( function testCannotOverridePropertiesWithGetterOrSetter( type, build ) -{ - setUp(); - - // declare a property - members[ 'public' ][ name ] = 'foo'; - - try - { - // attempt to override property with getter/setter (should fail) - build( { 'public': true }, null, true ); - } - catch ( e ) - { - assert.ok( e.message.search( name ) !== -1, - "Property override error message should contain getter/setter name" - ); - return; - } - - assert.fail( type + " should not be able to override properties" ); -} ); -