From e9cf630d0bdd010d5a30f5bd72b8516b14418260 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 20 Dec 2011 20:06:38 -0500 Subject: [PATCH] AbstractClass.implement().extend() will now properly preserve abstract flag on resulting class - This is a bug fix. The resulting class was not declared abstract, which is a problem if the resulting class chose not to provide a concrete implementation for each of the abstract members. --- lib/class_abstract.js | 14 ++++++++++++-- test/test-class-abstract.js | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/class_abstract.js b/lib/class_abstract.js index 5e04c6a..90adbe8 100644 --- a/lib/class_abstract.js +++ b/lib/class_abstract.js @@ -107,11 +107,19 @@ function markAbstract( args ) * * @param {Object} obj object to override * - * @return {undefined} + * @return {Object} obj */ function abstractOverride( obj ) { - var extend = obj.extend; + var extend = obj.extend, + impl = obj.implement; + + // wrap and apply the abstract flag, only if the method is defined (it may + // not be under all circumstances, e.g. after an implement()) + impl && ( obj.implement = function() + { + return abstractOverride( impl.apply( this, arguments ) ); + } ); // wrap extend, applying the abstract flag obj.extend = function() @@ -119,5 +127,7 @@ function abstractOverride( obj ) markAbstract( arguments ); return extend.apply( this, arguments ); }; + + return obj; } diff --git a/test/test-class-abstract.js b/test/test-class-abstract.js index 9ba4085..e33c8d2 100644 --- a/test/test-class-abstract.js +++ b/test/test-class-abstract.js @@ -26,7 +26,8 @@ var common = require( './common' ), util = common.require( 'util' ), Class = common.require( 'class' ), - AbstractClass = common.require( 'class_abstract' ) + AbstractClass = common.require( 'class_abstract' ), + Interface = common.require( 'interface' ) ; @@ -451,3 +452,22 @@ var ConcreteFoo = Class.extend( AbstractFoo, ); } )(); + +/** + * Extending an abstract class after an implement() should still result in an + * abstract class. Essentially, we are testing to ensure that the extend() + * method is properly wrapped to flag the resulting class as abstract. This was + * a bug. + */ +( function testImplementingInterfacesWillPreserveAbstractClassDeclaration() +{ + assert.doesNotThrow( function() + { + // if not considered abstract, extend() will fail, as it will contain + // abstract member foo + AbstractClass( 'TestImplExtend' ) + .implement( Interface( { foo: [] } ) ) + .extend( {} ); + }, Error, 'Class should still be abstract after implement().extend()' ); +} )() +