From e866f53d4c1c23fed0fba3c113c67fcff1817949 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Wed, 13 May 2015 00:18:08 -0400 Subject: [PATCH] Remove global _extending state The previous implementation could not survive recursive applications, which I did know about. But that was before the system was brutally abused by traits. --- lib/ClassBuilder.js | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js index 241d0df..59c961e 100644 --- a/lib/ClassBuilder.js +++ b/lib/ClassBuilder.js @@ -144,15 +144,6 @@ function ClassBuilder( warn_handler, member_builder, visibility_factory ) */ this._instanceId = 0; - /** - * Set to TRUE when class is in the process of being extended to ensure that - * a constructor can be instantiated (to use as the prototype) without - * invoking the class construction logic - * - * @type {boolean} - */ - this._extending = false; - /** * A flag to let the system know that we are currently attempting to access * a static property from within a method. This means that the caller should @@ -345,9 +336,6 @@ exports.prototype.build = function extend( _, __ ) { var build = this; - // ensure we'll be permitted to instantiate abstract classes for the base - this._extending = true; - var a = arguments, an = a.length, props = ( ( an > 0 ) ? a[ an - 1 ] : 0 ) || {}, @@ -500,15 +488,13 @@ exports.prototype.build = function extend( _, __ ) // (intended for use in prototype chains) new_class.asPrototype = function() { - build._extending = true; - var inst = new_class(); - build._extending = false; + new_class[ _priv ].extending = true; + var inst = new new_class(); + new_class[ _priv ].extending = false; + return inst; }; - // we're done with the extension process - this._extending = false; - return new_class; }; @@ -522,7 +508,9 @@ exports.prototype._getBase = function( base ) // 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(); + return ( base[ _priv ] ) + ? base.asPrototype() + : new base(); // we can use objects as the prototype directly case 'object': @@ -865,8 +853,8 @@ exports.prototype.createCtor = function( cname, abstract_methods, members ) */ exports.prototype.createConcreteCtor = function( cname, members ) { - var args = null, - _self = this; + var args = null, + _self = this; /** * Constructor function to be returned @@ -896,7 +884,7 @@ exports.prototype.createConcreteCtor = function( cname, members ) // If we're extending, we don't actually want to invoke any class // construction logic. The above is sufficient to use this class in a // prototype, so stop here. - if ( _self._extending ) + if ( ClassInstance[ _priv ].extending ) { return; } @@ -992,7 +980,7 @@ exports.prototype.createAbstractCtor = function( cname ) var __abstract_self = function() { - if ( !_self._extending ) + if ( !__abstract_self[ _priv ].extending ) { throw Error( "Abstract class " + ( cname || '(anonymous)' ) +