1
0
Fork 0

Began adding protected static members (supported for instance methods)

- No inheritance support yet
closure/master
Mike Gerwitz 2011-05-09 23:09:32 -04:00
parent 56ba57511b
commit a246dd67e0
2 changed files with 68 additions and 4 deletions

View File

@ -234,7 +234,7 @@ exports.build = function extend()
} }
staticInit( new_class, false ); staticInit( new_class, false );
attachPropInit( prototype, prop_init, members, class_id ); attachPropInit( prototype, prop_init, members, static_members, class_id );
new_class.prototype = prototype; new_class.prototype = prototype;
new_class.constructor = new_class; new_class.constructor = new_class;
@ -533,12 +533,13 @@ function buildMembers(
* @param {Object} properties properties to initialize * @param {Object} properties properties to initialize
* *
* @param {{public: Object, protected: Object, private: Object}} members * @param {{public: Object, protected: Object, private: Object}} members
* @param {{public: Object, protected: Object, private: Object}} static_members
* *
* @param {number} cid class id * @param {number} cid class id
* *
* @return {undefined} * @return {undefined}
*/ */
function attachPropInit( prototype, properties, members, cid ) function attachPropInit( prototype, properties, members, static_members, cid )
{ {
util.defineSecureProp( prototype, '__initProps', function( inherit ) util.defineSecureProp( prototype, '__initProps', function( inherit )
{ {
@ -573,6 +574,9 @@ function attachPropInit( prototype, properties, members, cid )
inst_props, properties, members inst_props, properties, members
); );
// give internal methods access to protected/private static members
initStaticVisibilityObj.call( this, vis, static_members );
// provide a means to access the actual instance (rather than the // provide a means to access the actual instance (rather than the
// property/visibility object) internally (this will translate to // property/visibility object) internally (this will translate to
// this.__inst from within a method), but only if we're on our final // this.__inst from within a method), but only if we're on our final
@ -585,6 +589,32 @@ function attachPropInit( prototype, properties, members, cid )
} }
/**
* Creates and populates the static visibility object
*
* This function should be called in the context of the class.
*
* @param {Object} vis class visibility object to attach to (override __self)
* @param {{public: Object, protected: Object, private: Object}} static_members
*
* @return {undefined}
*/
function initStaticVisibilityObj( vis, static_members )
{
// the object will simply be another layer in the prototype chain to
// prevent protected/private members from being mixed in with the public
var sobj = function() {};
sobj.prototype = this;
var sobji = new sobj();
util.copyTo( sobji, static_members.methods[ 'protected' ] );
// override __self on the instance's visibility object, giving internal
// methods access to the restricted static methods
vis.__self = sobji;
}
/** /**
* Attaches static members to a constructor (class) * Attaches static members to a constructor (class)
* *

View File

@ -43,7 +43,9 @@ var common = require( './common' ),
}, },
} ); } );
assert.deepEqual( Foo().test(), Foo, // we must use instanceof here because the __self object has the class in
// its prototype chain
assert.ok( Foo().test() instanceof Foo,
"__self property references class definition" "__self property references class definition"
); );
} )(); } )();
@ -427,3 +429,35 @@ var common = require( './common' ),
); );
} )(); } )();
/**
* Protected members should be available from within the class but shouldn't be
* exposed to the world
*/
( function testProtectedStaticMembersAreAvailableInsideClassOnly()
{
var val = 'foo',
Foo = builder.build(
{
// the same rules should apply to methods
'protected static baz': function()
{
return val;
},
// ensure method is accessible to instance methods
'public instBaz': function()
{
return this.__self.baz();
},
} );
assert.equal( Foo.baz, undefined,
"Protected methods should not be accessible outside the class"
);
assert.equal( Foo().instBaz(), val,
"Protected methods are accessible to instance methods"
);
} )();