2011-10-28 00:22:50 -04:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2013-12-20 00:49:06 -05:00
|
|
|
* Copyright (C) 2011 Mike Gerwitz
|
2011-10-28 00:22:50 -04:00
|
|
|
*
|
|
|
|
* This file is part of ease.js.
|
|
|
|
*
|
|
|
|
* ease.js is free software: you can redistribute it and/or modify it under the
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
* version.
|
2011-10-28 00:22:50 -04:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
2011-10-28 00:22:50 -04:00
|
|
|
*
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
2011-10-28 00:22:50 -04:00
|
|
|
*
|
|
|
|
* @author Mike Gerwitz
|
|
|
|
*/
|
|
|
|
|
|
|
|
var shared = require( __dirname + '/inc-common' );
|
|
|
|
|
|
|
|
require( 'common' ).testCase(
|
|
|
|
{
|
|
|
|
caseSetUp: function()
|
|
|
|
{
|
2011-10-30 12:06:09 -04:00
|
|
|
var _self = this;
|
|
|
|
|
2011-12-06 18:26:28 -05:00
|
|
|
this.quickFailureTest = function()
|
|
|
|
{
|
|
|
|
shared.quickFailureTest.apply( _self, arguments );
|
|
|
|
};
|
2011-10-30 12:06:09 -04:00
|
|
|
|
2011-12-22 22:05:47 -05:00
|
|
|
this.quickKeywordTest = function( keywords, identifier, prev )
|
|
|
|
{
|
|
|
|
shared.quickKeywordTest.call( this,
|
2011-12-22 23:10:01 -05:00
|
|
|
'validateGetterSetter', keywords, identifier, prev,
|
2011-12-22 23:25:35 -05:00
|
|
|
prev && { get: function() {}, set: function() {} }
|
2011-12-22 22:05:47 -05:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2011-12-03 00:30:22 -05:00
|
|
|
this.quickVisChangeTest = function( start, override, failtest, failstr )
|
2011-10-30 12:06:09 -04:00
|
|
|
{
|
|
|
|
shared.quickVisChangeTest.call( _self, start, override, failtest,
|
|
|
|
function( name, startobj, overrideobj )
|
|
|
|
{
|
2011-12-22 23:10:01 -05:00
|
|
|
startobj.virtual = true;
|
|
|
|
overrideobj.override = true;
|
|
|
|
|
2011-10-30 12:06:09 -04:00
|
|
|
_self.sut.validateGetterSetter(
|
2011-11-05 09:40:56 -04:00
|
|
|
name, {}, overrideobj,
|
2011-10-30 12:06:09 -04:00
|
|
|
{ get: function() {}, set: function() {} },
|
|
|
|
startobj
|
|
|
|
);
|
2011-12-03 00:30:22 -05:00
|
|
|
},
|
|
|
|
failstr
|
2011-10-30 12:06:09 -04:00
|
|
|
);
|
|
|
|
};
|
2011-10-28 00:22:50 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
setUp: function()
|
|
|
|
{
|
2011-12-22 23:32:45 -05:00
|
|
|
var _self = this;
|
|
|
|
|
|
|
|
// can be used to intercept warnings; redefine in test
|
|
|
|
this.warningHandler = function( warning ) {};
|
|
|
|
|
|
|
|
this.sut = this.require( 'MemberBuilderValidator' )(
|
|
|
|
function( warning )
|
|
|
|
{
|
|
|
|
_self.warningHandler( warning );
|
|
|
|
}
|
|
|
|
);
|
2011-10-28 00:22:50 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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(
|
2011-11-05 09:40:56 -04:00
|
|
|
name, {}, {}, { member: function() {} }
|
2011-10-28 00:22:50 -04:00
|
|
|
);
|
|
|
|
} );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
'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(
|
2011-11-05 09:40:56 -04:00
|
|
|
name, {}, {}, { member: 'foo' }
|
2011-10-28 00:22:50 -04:00
|
|
|
);
|
|
|
|
} );
|
2011-10-30 12:06:09 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* De-escalating the visibility of any member would alter the interface of a
|
|
|
|
* subtype, which would not be polymorphic.
|
|
|
|
*/
|
|
|
|
'Getters/setters do not support visibility de-escalation': function()
|
|
|
|
{
|
|
|
|
this.quickVisChangeTest( 'public', 'protected', true );
|
|
|
|
this.quickVisChangeTest( 'protected', 'private', true );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Contrary to the above test, we have no such problem with visibility
|
|
|
|
* escalation.
|
|
|
|
*/
|
|
|
|
'Getters/setters support visibility escalation and equality': function()
|
|
|
|
{
|
|
|
|
var _self = this;
|
|
|
|
shared.visEscalationTest( function( cur )
|
|
|
|
{
|
|
|
|
_self.quickVisChangeTest( cur[ 0 ], cur[ 1 ], false );
|
|
|
|
} );
|
|
|
|
},
|
2011-12-03 00:30:22 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See property/method tests for more information. This is not strictly
|
|
|
|
* necessary (since getters/setters can exist only in an ES5+ environment),
|
|
|
|
* but it's provided for consistency. It's also easy to remove this feature
|
|
|
|
* without breaking BC. The reverse is untrue.
|
|
|
|
*/
|
|
|
|
'Cannot redeclare private getters/setters in subtypes': function()
|
|
|
|
{
|
|
|
|
var _self = this;
|
|
|
|
shared.privateNamingConflictTest( function( cur )
|
|
|
|
{
|
|
|
|
_self.quickVisChangeTest( cur[ 0 ], cur[ 1 ], true, 'conflict' );
|
|
|
|
} );
|
|
|
|
},
|
2011-12-22 22:05:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract getter/setters are not yet supported. They may be supported in
|
|
|
|
* the future. Disallowing them now will allow us to determine an
|
|
|
|
* implementation in the future without breaking BC.
|
|
|
|
*/
|
|
|
|
'Cannot declare abstract getters/setters': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'abstract' ], 'abstract' );
|
|
|
|
},
|
2011-12-22 22:48:17 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* As getters/setters are essentially methods, they are treated very
|
|
|
|
* similarity. They cannot be declared as const. Rather, that should be
|
|
|
|
* handled by omitting a setter.
|
|
|
|
*/
|
|
|
|
'Cannot declare const getters/setters': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'const' ], 'const' );
|
|
|
|
},
|
2011-12-22 23:10:01 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Getters/setters can be overridden just like methods, so long as they
|
|
|
|
* follow the same keyword restrictions.
|
|
|
|
*/
|
|
|
|
'Can override virtual getter/setter with override keyword': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'override' ], null, [ 'virtual' ] );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The 'override' keyword must be provided if a member is being overridden.
|
|
|
|
*/
|
|
|
|
'Must provide override keyword when overriding getter/setter': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [], 'override', [ 'virtual' ] );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Just like methods, getters/setters may only be overridden if they have
|
|
|
|
* been declared 'virtual'.
|
|
|
|
*/
|
|
|
|
'Cannot override non-virtual getter/setter': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'override' ], 'non-virtual', [] );
|
|
|
|
},
|
2011-12-22 23:25:35 -05:00
|
|
|
|
|
|
|
|
|
|
|
'Can declare getter/setter as static': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'static' ] );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* As static members cannot be overridden, it does not make sense to permit
|
|
|
|
* the 'static' and 'virtual' keywords to be used together.
|
|
|
|
*/
|
|
|
|
'Cannot declare getter/setter as both static and virtual': function()
|
|
|
|
{
|
|
|
|
this.quickKeywordTest( [ 'static', 'virtual' ], 'static' );
|
|
|
|
},
|
2011-12-22 23:32:45 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If a developer uses the 'override' keyword when there is no super member
|
|
|
|
* to override, this could hint at a number of problems (see MethodTest for
|
|
|
|
* further discussion).
|
|
|
|
*/
|
|
|
|
'Throws warning when using override with no super getter/setter': function()
|
|
|
|
{
|
|
|
|
var given = null;
|
|
|
|
|
|
|
|
this.warningHandler = function( warning )
|
|
|
|
{
|
|
|
|
given = warning;
|
|
|
|
};
|
|
|
|
|
|
|
|
// trigger warning (override keyword with no super method)
|
|
|
|
this.quickKeywordTest( [ 'override' ] );
|
|
|
|
|
|
|
|
this.assertNotEqual( null, given,
|
|
|
|
'No warning was provided'
|
|
|
|
);
|
|
|
|
|
|
|
|
this.assertOk( given instanceof Error,
|
|
|
|
'Provided warning is not of type Error'
|
|
|
|
);
|
|
|
|
|
|
|
|
this.assertOk( ( given.message.search( shared.testName ) > -1 ),
|
|
|
|
'Override warning should contain getter/setter name'
|
|
|
|
);
|
|
|
|
},
|
2011-10-28 00:22:50 -04:00
|
|
|
} );
|