From fad503422efce0517c3d5b094ab68fd9c1ea549d Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 5 Apr 2011 23:11:25 -0400 Subject: [PATCH] Subtypes now inherit public static members from their supertype --- lib/class_builder.js | 19 ++++++- test/test-class_builder-static.js | 85 +++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/lib/class_builder.js b/lib/class_builder.js index 4456697..660458a 100644 --- a/lib/class_builder.js +++ b/lib/class_builder.js @@ -203,13 +203,20 @@ exports.build = function extend() // set up the new class var new_class = createCtor( cname, abstract_methods, members ); - attachStatic( new_class, static_members ); + // closure to hold static initialization to be used later by subtypes + var staticInit = function( ctor ) + { + attachStatic( ctor, static_members, base ); + } + staticInit( new_class ); + attachPropInit( prototype, prop_init, members, class_id ); new_class.prototype = prototype; new_class.constructor = new_class; new_class.___$$props$$ = prop_init; new_class.___$$methods$$ = members; + new_class.___$$sinit$$ = staticInit; // We reduce the overall cost of this definition by defining it on the // prototype rather than during instantiation. While this does increase the @@ -558,8 +565,16 @@ function attachPropInit( prototype, properties, members, cid ) * * @return {undefined} */ -function attachStatic( ctor, members ) +function attachStatic( ctor, members, base ) { + // "inherit" the parent's static members by running the parent's static + // initialization method + var baseinit = base.___$$sinit$$; + if ( baseinit ) + { + baseinit( ctor ); + } + // copy over public static members util.copyTo( ctor, members[ 'public' ] ); } diff --git a/test/test-class_builder-static.js b/test/test-class_builder-static.js index 77ba8f2..2b07a56 100644 --- a/test/test-class_builder-static.js +++ b/test/test-class_builder-static.js @@ -201,3 +201,88 @@ var common = require( './common' ), ); } )(); + +/** + * We don't have the benefit of static members being part of the prototype + * chain. Inheritance is not automatic. This test deals only with ensuring that + * *public* static members are inherited by subtypes. + */ +( function testPublicStaticMembersAreInheritedBySubtypes() +{ + var def = { + 'public static foo': 'val', + 'public static func': function() {}, + + 'public bla': 'moo', + }; + + // also test getters/setters if supported + if ( !fallback ) + { + Object.defineProperty( def, 'public static bar', { + get: function() {}, + set: function() {}, + + enumerable: true, + } ); + } + + var baz = 'foobar', + Foo = builder.build( def ), + + // extends from the parent and adds an additional + SubFoo = builder.build( Foo, { 'public static baz': baz } ), + + // simply extends from the parent (also serves as a check to ensure that + // static members of *all* parents are inherited, not just the + // immediate) + SubSubFoo = builder.build( SubFoo, {} ) + ; + + // properties + assert.equal( SubFoo.foo, Foo.foo, + "Public static properties are inherited by subtypes" + ); + assert.equal( SubSubFoo.foo, Foo.foo, + "Public static properties are inherited by sub-subtypes" + ); + + // methods + assert.deepEqual( SubFoo.func, Foo.func, + "Public static methods are inherited by subtypes" + ); + assert.deepEqual( SubSubFoo.func, Foo.func, + "Public static methods are inherited by sub-subtypes" + ); + + // merge + assert.equal( SubFoo.baz, baz, + "Subtypes contain both inherited static members as well as their own" + ); + + // getters/setters (if supported by engine) + if ( !fallback ) + { + var super_data = Object.getOwnPropertyDescriptor( Foo, 'bar' ), + sub_data = Object.getOwnPropertyDescriptor( SubFoo, 'bar' ), + sub_sub_data = Object.getOwnPropertyDescriptor( SubFoo, 'bar' ) + ; + + // getters + assert.deepEqual( super_data.get, sub_data.get, + "Public static getters are inherited by subtypes" + ); + assert.deepEqual( super_data.get, sub_sub_data.get, + "Public static getters are inherited by sub-subtypes" + ); + + // setters + assert.deepEqual( super_data.set, sub_data.set, + "Public static setters are inherited by subtypes" + ); + assert.deepEqual( super_data.set, sub_sub_data.set, + "Public static setters are inherited by sub-subtypes" + ); + } +} )(); +