1
0
Fork 0

Now properly handling extending from objects and properly throwing errors for scalars

perfodd
Mike Gerwitz 2011-12-15 22:58:23 -05:00
parent d5ef3eb221
commit 2136ebedd5
2 changed files with 56 additions and 9 deletions

View File

@ -294,7 +294,7 @@ exports.prototype.build = function extend( _, __ )
var args = Array.prototype.slice.call( arguments ),
props = args.pop() || {},
base = args.pop() || exports.ClassBase,
prototype = new base(),
prototype = this._getBase( base ),
cname = '',
prop_init = this._memberBuilder.initMembers(),
@ -309,12 +309,6 @@ exports.prototype.build = function extend( _, __ )
|| { __length: 0 }
;
// must extend from constructor or class
if ( typeof base !== 'function' )
{
throw TypeError( "Must extend from class or constructor");
}
// prevent extending final classes
if ( base.___$$final$$ === true )
{
@ -424,6 +418,27 @@ exports.prototype.build = function extend( _, __ )
};
exports.prototype._getBase = function( base )
{
var type = ( typeof base );
switch ( type )
{
// constructor (we could also check to ensure that the return value of
// the constructor is an object, but that is not our concern)
case 'function':
return new base();
// we can use objects as the prototype directly
case 'object':
return base;
}
// scalars
throw TypeError( 'Must extend from Class, constructor or object' );
};
exports.prototype.buildMembers = function buildMembers(
props, class_id, base, prop_init, abstract_methods, members,
static_members, staticInstLookup
@ -758,11 +773,12 @@ exports.prototype._attachPropInit = function(
// defaults to false
inherit = !!inherit;
var iid = this.__iid;
var iid = this.__iid,
parent = prototype.___$$parent$$;
// first initialize the parent's properties, so that ours will overwrite
// them
var parent_init = prototype.___$$parent$$.__initProps;
var parent_init = parent && parent.__initProps;
if ( typeof parent_init === 'function' )
{
// call the parent prop_init, letting it know that it's been

View File

@ -432,3 +432,34 @@ for ( var i = 0; i < class_count; i++ )
assert.fail( "Should not be permitted to override non-virtual method" );
} )();
/**
* If we attempt to extend an object (rather than a constructor), we should
* simply use that as the prototype directly rather than attempting to
* instantiate it.
*/
( function testExtendingObjectWillNotAttemptInstantiation()
{
var obj = { foo: 'bar' };
assert.equal( obj.foo, Class.extend( obj, {} )().foo,
'Should be able to use object as prototype'
);
} )();
/**
* It only makes sense to extend from an object or function (constructor, more
* specifically)
*
* We could also test to ensure that the return value of the constructor is an
* object, but that is unnecessary for the time being.
*/
( function testWillThrowExceptionIfNonObjectOrCtorIsProvided()
{
assert['throws']( function()
{
Class.extend( 'foo', {} );
}, TypeError, 'Should not be able to extend from non-object or non-ctor' );
} )();