From 66758500e65804ec2f40186b6f25e6498eff0b97 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 14 Mar 2011 23:43:56 -0400 Subject: [PATCH] Class metadata is now stored in class object (first step in working with GC) --- lib/class.js | 49 ++++++++++++++++++--------------------- test/test-class-parent.js | 18 -------------- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/lib/class.js b/lib/class.js index 08f6a84..8ec561d 100644 --- a/lib/class.js +++ b/lib/class.js @@ -27,14 +27,6 @@ var util = require( './util' ), propobj = require( './propobj' ) ; -/** - * Stores class metadata internally (ensures data is encapsulated) - * - * The data in this object is hashed a class id. - * - * @type {Object. }>} - */ -var class_meta = {}; /** * Stores class instance visibility object @@ -217,7 +209,7 @@ module.exports.isInstanceOf = function( type, instance ) // if no metadata is available, then our remaining checks cannot be // performed - if ( !instance.__cid || !( meta = getMeta( instance.__cid ) ) ) + if ( !instance.__cid || !( meta = getMeta( instance ) ) ) { return false; } @@ -450,7 +442,7 @@ var extend = ( function( extending ) members = member_builder.initMembers( prototype ), abstract_methods = - util.clone( getMeta( base.__cid ).abstractMethods ) + util.clone( getMeta( base ).abstractMethods ) || { __length: 0 } ; @@ -543,7 +535,7 @@ var extend = ( function( extending ) } ); // reference to the parent prototype (for more experienced users) - prototype.parent = base.prototype; + prototype.___$$parent$$ = base.prototype; // set up the new class var new_class = createCtor( cname, abstract_methods, members ); @@ -556,15 +548,15 @@ var extend = ( function( extending ) // important: call after setting prototype setupProps( new_class, abstract_methods, class_id ); + // create internal metadata for the new class + var meta = createMeta( new_class, base ); + meta.abstractMethods = abstract_methods; + meta.name = cname; + // lock down the new class (if supported) to ensure that we can't add // members at runtime util.freeze( new_class ); - // create internal metadata for the new class - var meta = createMeta( new_class, base.prototype.__cid ); - meta.abstractMethods = abstract_methods; - meta.name = cname; - // we're done with the extension process extending = false; @@ -724,7 +716,7 @@ var implement = function() // create a new class with the implemented abstract methods var class_new = module.exports.extend( base, dest ); - getMeta( class_new.__cid ).implemented = implemented; + getMeta( class_new ).implemented = implemented; return class_new; } @@ -801,7 +793,7 @@ function attachPropInit( prototype, properties, members, cid ) // first initialize the parent's properties, so that ours will overwrite // them - var parent_init = prototype.parent.__initProps; + var parent_init = prototype.___$$parent$$.__initProps; if ( parent_init instanceof Function ) { // call the parent prop_init, letting it know that it's been @@ -952,29 +944,34 @@ function attachInstanceOf( instance ) /** * Initializes class metadata for the given class * - * @param {Class} func class to initialize metadata for + * @param {Class} func class to initialize metadata for + * @param {Class} cparent class parent * * @return {undefined} */ -function createMeta( func, parent_id ) +function createMeta( func, cparent ) { var id = func.__cid, - parent_meta = ( ( parent_id ) ? getMeta( parent_id ) : undefined ); + parent_meta = ( ( cparent.__cid ) ? getMeta( cparent ) : undefined ); // copy the parent prototype's metadata if it exists (inherit metadata) if ( parent_meta ) { - class_meta[ id ] = util.clone( parent_meta, true ); + func.___$$meta$$ = util.clone( parent_meta, true ); } else { // create empty - class_meta[ id ] = { + func.___$$meta$$ = { implemented: [], }; } - return class_meta[ id ]; + // store the metadata in the prototype as well (inconsiderable overhead; + // it's just a reference) + func.prototype.___$$meta$$ = func.___$$meta$$; + + return func.___$$meta$$; } @@ -988,9 +985,9 @@ function createMeta( func, parent_id ) * * @return {Object} */ -function getMeta( id ) +function getMeta( cls ) { - return class_meta[ id ] || {}; + return cls.___$$meta$$ || {}; } diff --git a/test/test-class-parent.js b/test/test-class-parent.js index 1efd5f2..6ef8d64 100644 --- a/test/test-class-parent.js +++ b/test/test-class-parent.js @@ -60,11 +60,6 @@ var common = require( './common' ), { return this.__super( arg ); }, - - callParentAlt: function() - { - return this.parent.myMethod2.apply( this, arguments ); - }, }), foo = new Foo(), @@ -109,19 +104,6 @@ assert.equal( "Arguments should be passed to super method via _super argument list" ); -assert.deepEqual( - SubFoo.prototype.parent, - Foo.prototype, - "Parent property should represent parent prototype" -); - -sub_foo.callParentAlt( arg = 'moo' ); -assert.equal( - method2Arg, - arg, - "The parent property may also be used to invoke parent methods" -); - assert.throws( function() { Foo.extend(