From 1d9c06a16984c24d334bcdcf4962724d94b5c79b Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Sat, 4 Nov 2017 14:51:29 -0400 Subject: [PATCH] Properly handle error subtype #constructor (#__constructor alias) Using `#constructor' in place of `#__construct' caused an error attempting to "redefine" `#__constructor' (once the alias was applied); the system was making improper assumptions and not accounting for aliases. In fact, everthing about how this was being done was bad, since adding any keywords would have thrown it off as well! * lib/ClassBuilder.js (build): Move ector detection past prop parsing. Check parsed properties instead of raw. * test/ClassBuilder/ErrorExtendTest.js: Iterate ctor override test on new `ctors'. (caseSetUp) [ctors]: Add property. --- lib/ClassBuilder.js | 34 +++++++++++++++------------- test/ClassBuilder/ErrorExtendTest.js | 17 ++++++++------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js index 4d5430c..50d19a1 100644 --- a/lib/ClassBuilder.js +++ b/lib/ClassBuilder.js @@ -447,22 +447,6 @@ exports.prototype.build = function extend( _, __ ) } } - // we transparently handle extending errors in a sane manner, which is - // traditionally a huge mess (you're welcome) - if ( this._ector && this._ector.isError( base ) ) - { - // declare public properties (otherwise, they'll be confined to the - // private visibility object in ES5+ environments) - props.message = ''; - props.stack = ''; - - // user-provided constructor - var ector_own = props.__construct; - - // everything else is handled by the constructor - props.__construct = this._ector.createCtor( base, cname, ector_own ); - } - // increment class identifier this._classId++; @@ -508,6 +492,24 @@ exports.prototype.build = function extend( _, __ ) } } + // we transparently handle extending errors in a sane manner, which is + // traditionally a huge mess (you're welcome) + if ( this._ector && this._ector.isError( base ) ) + { + // declare public properties (otherwise, they'll be confined to the + // private visibility object in ES5+ environments) + props.message = ''; + props.stack = ''; + + // user-provided constructor + var ector_own = members[ 'public' ].__construct; + + // everything else is handled by the constructor + members[ 'public' ].__construct = this._ector.createCtor( + base, cname, ector_own + ); + } + // reference to the parent prototype (for more experienced users) prototype.___$$parent$$ = base.prototype; diff --git a/test/ClassBuilder/ErrorExtendTest.js b/test/ClassBuilder/ErrorExtendTest.js index 5bd6007..647d552 100644 --- a/test/ClassBuilder/ErrorExtendTest.js +++ b/test/ClassBuilder/ErrorExtendTest.js @@ -38,6 +38,8 @@ require( 'common' ).testCase( RangeError, URIError, ]; + + this.ctors = [ '__construct', 'constructor' ]; }, @@ -164,7 +166,7 @@ require( 'common' ).testCase( * implementation. However, a user can provide a method to be invoked * after the generated constructor. */ - 'Can override generated constructor': function() + '@each(ctors) Can override generated constructor': function( ctor ) { var called_gen = false, called_own = false; @@ -178,12 +180,13 @@ require( 'common' ).testCase( }; }; - var result = this.builder.build( {}, { - __construct: function() - { - called_own = true; - }, - } )(); + var dfn = {}; + dfn[ ctor ] = function() + { + called_own = true; + }; + + var result = this.builder.build( {}, dfn )(); this.assertOk( called_gen ); this.assertOk( called_own );