From 7f8d2658779c04246bed9743244a265224544021 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 24 Feb 2014 23:03:04 -0500 Subject: [PATCH] Corrected override of super-super methods More generally, this was a problem with not recursing on *all* of the visibility objects of the supertype's supertype; the public visibility object was implicitly recursed upon through JavaScript's natural prototype chain, so this only manifested itself with protected members. --- lib/MemberBuilder.js | 10 ++++++++-- test/Class/ExtendTest.js | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/MemberBuilder.js b/lib/MemberBuilder.js index 18e45e5..51f8bb3 100644 --- a/lib/MemberBuilder.js +++ b/lib/MemberBuilder.js @@ -356,9 +356,15 @@ function scanMembers( members, name, base ) var base_methods = base.___$$methods$$, base_props = base.___$$props$$; + // we must recurse on *all* the visibility objects of the base's + // supertype; attempt to find the class associated with its + // supertype, if any + var base2 = ( ( base.prototype || {} ).___$$parent$$ || {} ) + .constructor; + // scan the base's methods and properties, if they are available - return ( base_methods && scanMembers( base_methods, name ) ) - || ( base_props && scanMembers( base_props, name ) ) + return ( base_methods && scanMembers( base_methods, name, base2 ) ) + || ( base_props && scanMembers( base_props, name, base2 ) ) || null ; } diff --git a/test/Class/ExtendTest.js b/test/Class/ExtendTest.js index 416ec44..3d58365 100644 --- a/test/Class/ExtendTest.js +++ b/test/Class/ExtendTest.js @@ -428,4 +428,44 @@ require( 'common' ).testCase( "Should be able to use object as prototype" ); }, + + + /** + * Gathering metadata on public methods of supertypes N>1 distance away + * is easy, as it is part of the public prototype chain that is + * naturally traversed by JavaScript. However, we must ensure that we + * properly recurse on *all* visibility objects. + * + * This test addresses a pretty alarming bug that was not caught during + * initial development---indeed, until the trait implementation, which + * exploits the class system in some odd ways---because the author + * dislikes inheritence in general, letalone large hierarchies, so + * protected members of super-supertypes seems to have gone untested. + */ + 'Extending validates against non-public super-supertype methods': + function() + { + var called = false; + + this.Sut.extend( + { + 'virtual protected foo': function() + { + called = true; + } + } ).extend( + { + // intermediate to disconnect subtype + } ).extend( + { + 'override public foo': function() + { + this.__super(); + } + } )().foo(); + + // the override would have only actually taken place if the + // protected foo was recognized + this.assertOk( called ); + }, } );