2014-01-15 23:34:26 -05:00
|
|
|
/**
|
|
|
|
* Tests class module constructor creation
|
|
|
|
*
|
2017-11-04 15:08:02 -04:00
|
|
|
* Copyright (C) 2014, 2015, 2016 Free Software Foundation, Inc.
|
2014-01-15 23:34:26 -05:00
|
|
|
*
|
|
|
|
* This file is part of GNU ease.js.
|
|
|
|
*
|
|
|
|
* ease.js is free software: you can redistribute it and/or modify
|
|
|
|
* it under the 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.
|
|
|
|
*
|
|
|
|
* 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
require( 'common' ).testCase(
|
|
|
|
{
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
caseSetUp: function()
|
|
|
|
{
|
|
|
|
// ease.js was written long before ES6 drafts began providing class
|
|
|
|
// support. Now that they do, we should support their constructor
|
|
|
|
// decision as well as our own.
|
|
|
|
this.ctors = [ '__construct', 'constructor' ];
|
|
|
|
|
|
|
|
// we only use ES3 features, thus this
|
|
|
|
this.mkctor = function( name, f )
|
|
|
|
{
|
|
|
|
var o = {};
|
|
|
|
o[ name ] = f;
|
|
|
|
|
|
|
|
return o;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2014-01-15 23:34:26 -05:00
|
|
|
setUp: function()
|
|
|
|
{
|
|
|
|
this.Sut = this.require( 'class' );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* As a sanity check, ensure that the constructor is not invoked upon
|
|
|
|
* defining the class. (Note that the case of ensuring that it is not
|
|
|
|
* called when creating a subtype is handled by the ExtendTest case.)
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors) Should not be invoked before instantiation':
|
|
|
|
function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
var called = false,
|
|
|
|
dfn = {};
|
|
|
|
|
|
|
|
this.Sut.extend(
|
|
|
|
this.mkctor( name, function() { called = true; } )
|
|
|
|
);
|
2014-01-15 23:34:26 -05:00
|
|
|
|
|
|
|
this.assertNotEqual( called, true );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Since __construct is a special method that is not recognized by
|
|
|
|
* ECMAScript itself, we must ensure that it is invoked when the class
|
|
|
|
* is instantiated. Further, it should only be called a single time,
|
|
|
|
* which is particularly important if it produces side-effects.
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors) Should be invoked once upon instantiation':
|
|
|
|
function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
var called = 0;
|
|
|
|
|
|
|
|
var Foo = this.Sut.extend(
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
this.mkctor( name, function() { called++; } )
|
|
|
|
);
|
2014-01-15 23:34:26 -05:00
|
|
|
|
|
|
|
// note that we're not yet testing the more consise new-less
|
|
|
|
// invocation style
|
|
|
|
new Foo();
|
|
|
|
this.assertEqual( called, 1 );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Once invoked, the __construct method should be bound to the newly
|
|
|
|
* created instance.
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors) Should be invoked within context of new instance':
|
|
|
|
function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
var expected = Math.random();
|
|
|
|
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
var dfn = this.mkctor( name, function()
|
|
|
|
{
|
|
|
|
this.val = expected;
|
|
|
|
} );
|
|
|
|
|
|
|
|
dfn.val = null;
|
|
|
|
|
|
|
|
var Foo = this.Sut.extend( dfn );
|
2014-01-15 23:34:26 -05:00
|
|
|
|
|
|
|
// if `this' was bound to the instance, then __construct should set
|
|
|
|
// VAL to EXPECTED
|
|
|
|
var inst = new Foo();
|
|
|
|
this.assertEqual( inst.val, expected );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* All arguments passed to the constructor (that is, by invoking the
|
|
|
|
* ``class'') should be passed to __construct, unchanged and
|
|
|
|
* uncopied---that is, references should be retained.
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors) Arguments should be passed unchanged to __construct':
|
|
|
|
function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
var args = [ "foo", { bar: 'baz' }, [ 'moo', 'cow' ] ],
|
|
|
|
given = null;
|
|
|
|
|
|
|
|
var Foo = this.Sut.extend(
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
this.mkctor( name, function()
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
given = Array.prototype.slice.call( arguments, 0 );
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
} )
|
|
|
|
);
|
2014-01-15 23:34:26 -05:00
|
|
|
|
|
|
|
new Foo( args[ 0 ], args[ 1 ], args[ 2 ] );
|
|
|
|
|
|
|
|
// make sure we have everything and didn't get anything extra
|
|
|
|
this.assertEqual( given.length, args.length );
|
|
|
|
|
|
|
|
var i = args.length;
|
|
|
|
while ( i-- )
|
|
|
|
{
|
|
|
|
this.assertStrictEqual( given[ i ], args[ i ],
|
|
|
|
"Ctor argument mismatch: " + i
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If a subtype does not define its own constructor, then its parent's
|
|
|
|
* should be called by default. Note that this behavior---as is clear by
|
|
|
|
* the name __construct---is modelled after PHP; Java classes, for
|
|
|
|
* instance, do not inherit their parents' constructors.
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors)Parent constructor invoked for subtype if not overridden':
|
|
|
|
function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
var called = false;
|
|
|
|
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
var dfn = {};
|
|
|
|
dfn[ name ] = function() { called = true; };
|
|
|
|
|
|
|
|
var Sub = this.Sut.extend( dfn )
|
|
|
|
.extend( {} );
|
2014-01-15 23:34:26 -05:00
|
|
|
|
|
|
|
new Sub();
|
|
|
|
this.assertOk( called );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Classes created through ease.js do not require use of the `new'
|
|
|
|
* keyword, which allows for a much more natural, concise, and less
|
|
|
|
* error-prone syntax. Ensure that a new instance is created even when
|
|
|
|
* it is omitted.
|
|
|
|
*
|
|
|
|
* The rest of the tests above would then stand, since they use the
|
|
|
|
* `new' keyword and this concise format has no choice but to ultimately
|
|
|
|
* do the same; otherwise, it would not be recognized by instanceof.
|
|
|
|
*/
|
|
|
|
'Constructor does not require `new\' keyword': function()
|
|
|
|
{
|
|
|
|
var Foo = this.Sut.extend( {} );
|
|
|
|
|
|
|
|
this.assertOk( new Foo() instanceof Foo ); // sanity check
|
|
|
|
this.assertOk( Foo() instanceof Foo );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* In certain OO languages, one would prevent a class from being
|
|
|
|
* instantiated by declaring the constructor as protected or private. To
|
|
|
|
* me (Mike Gerwitz), this is cryptic. A better method would simply be
|
|
|
|
* to throw an exception. Perhaps, in the future, an alternative will be
|
|
|
|
* provided for consistency.
|
|
|
|
*
|
|
|
|
* The constructor must be public. (It is for this reason that you will
|
|
|
|
* often see the convention of omitting visibility keywords entirely for
|
|
|
|
* __construct, since public is the default and there is no other
|
|
|
|
* option.)
|
|
|
|
*/
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
'@each(ctors) Constructor must be public': function( name )
|
2014-01-15 23:34:26 -05:00
|
|
|
{
|
|
|
|
var Sut = this.Sut;
|
|
|
|
|
|
|
|
this.assertThrows( function()
|
|
|
|
{
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
var dfn = {};
|
|
|
|
dfn[ 'protected ' + name ] = function() {};
|
|
|
|
Sut( dfn );
|
2014-01-15 23:34:26 -05:00
|
|
|
}, TypeError, "Constructor should not be able to be protected" );
|
|
|
|
|
|
|
|
this.assertThrows( function()
|
|
|
|
{
|
Alias `constructor` member to `__construct`
This allows ease.js classes to mimic the structure of ES6 classes, which use
`constructor` to denote the constructor. This patch simply aliases it to
`__construct`, which ease.js handles as it would normally.
To that note, since the ES6 `class` keyword is purely syntatic sugar around
the prototype model, there is not much benefit to using it over ease.js if
benefits of ease.js are still desired, since the member definition syntax is
a feature of object literals:
```
// ease.js using ES6
let Person = Class(
{
_name: '',
// note that __construct still works as well
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
},
// keywords still work as expected
'protected getName'() {
return this._name;
}
} );
// ES6 using `class` keyword
class Person
{
// note that ES6 will _not_ make this private
_name: '',
constructor( name ) {
this._name = ''+name;
},
sayHi() {
return "Hi, I'm " + this.getName();
}
// keywords unsupported (you'd have to use Symbols)
getName() {
return this._name;
}
}
// ES3/5 ease.js
var Person = Class(
{
_name: '',
__construct: function( name ) {
this._name = ''+name;
},
sayHi: function() {
return "Hi, I'm " + this._name;
},
'protected getName': function() {
return this._name;
}
} );
```
As you can see, the only change between writing ES6-style method definitions
is the syntax; all keywords and other features continue to work as expected.
2015-09-15 00:10:07 -04:00
|
|
|
var dfn = {};
|
|
|
|
dfn[ 'private ' + name ] = function() {};
|
|
|
|
Sut( dfn );
|
2014-01-15 23:34:26 -05:00
|
|
|
}, TypeError, "Constructor should not be able to be private" );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2017-01-02 23:28:28 -05:00
|
|
|
/**
|
|
|
|
* This one is a bit of an interesting case. Information can be found
|
|
|
|
* in the manual, but for the sake of this test, all we need to know is
|
|
|
|
* that we should be able to override `__construct' without having
|
|
|
|
* provided the `virtual' keyword on the supertype. This differs from
|
|
|
|
* all other methods which are non-virtual by default.
|
|
|
|
*/
|
|
|
|
'@each(ctors) Constructor is virtual by default': function( name )
|
|
|
|
{
|
|
|
|
var _self = this;
|
|
|
|
|
|
|
|
this.assertDoesNotThrow( function()
|
|
|
|
{
|
|
|
|
var sub_called = false;
|
|
|
|
|
|
|
|
// not explicitly virtual
|
|
|
|
var base_dfn = {};
|
|
|
|
base_dfn[ name ] = function() {};
|
|
|
|
|
|
|
|
var sub_dfn = {};
|
|
|
|
sub_dfn[ 'override ' + name ] = function()
|
|
|
|
{
|
|
|
|
sub_called = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
_self.Sut.extend( _self.Sut( base_dfn ), sub_dfn )();
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
_self.assertOk( sub_called );
|
|
|
|
}, Error );
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2014-01-15 23:34:26 -05:00
|
|
|
/**
|
|
|
|
* When a constructor is instantiated conventionally in ECMAScript, the
|
|
|
|
* instance's `constructor' property is set to the constructor that was
|
|
|
|
* used to instantiate it. The same should be true for class instances.
|
|
|
|
*
|
|
|
|
* This will also be important for reflection.
|
|
|
|
*/
|
|
|
|
'`constructor\' property is properly set to class object': function()
|
|
|
|
{
|
|
|
|
var Foo = this.Sut.extend( {} );
|
|
|
|
this.assertStrictEqual( Foo().constructor, Foo );
|
|
|
|
},
|
2015-09-15 23:57:46 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We support multiple constructor styles; only one may be provided.
|
|
|
|
*
|
|
|
|
* This error should happen as a consequence of other method checks that
|
|
|
|
* prohibit redefinitions.
|
|
|
|
*/
|
|
|
|
'Cannot provide multiple constructor styles': function()
|
|
|
|
{
|
|
|
|
var Sut = this.Sut,
|
|
|
|
len = this.ctors.length;
|
|
|
|
|
|
|
|
// this will not test every permutation, but will hopefully be a
|
|
|
|
// reasonable test in the event that any additional constructors are
|
|
|
|
// added in the future (we start at 1 because it'll wrap modulo LEN)
|
|
|
|
for ( var i = 1; i < len; i++ )
|
|
|
|
{
|
|
|
|
var dfn = {},
|
|
|
|
a = this.ctors[ i ],
|
|
|
|
b = this.ctors[ ( i + 1 ) % len ];
|
|
|
|
|
|
|
|
dfn[ a ] = function() {};
|
|
|
|
dfn[ b ] = function() {};
|
|
|
|
|
|
|
|
this.assertThrows( function()
|
|
|
|
{
|
|
|
|
Sut( dfn );
|
|
|
|
}, Error, "Multiple constructors should not be permitted" );
|
|
|
|
}
|
|
|
|
},
|
2014-01-15 23:34:26 -05:00
|
|
|
} );
|