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 );
attachPropInit( prototype, prop_init, members, class_id );
attachPropInit( prototype, prop_init, members, static_members, class_id );
new_class.prototype = prototype;
new_class.constructor = new_class;
@ -533,12 +533,13 @@ function buildMembers(
* @param {Object} properties properties to initialize
*
* @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}
*/
function attachPropInit( prototype, properties, members, cid )
function attachPropInit( prototype, properties, members, static_members, cid )
{
util.defineSecureProp( prototype, '__initProps', function( inherit )
{
@ -573,6 +574,9 @@ function attachPropInit( prototype, properties, members, cid )
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
// property/visibility object) internally (this will translate to
// 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)
*

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"
);
} )();
@ -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"
);
} )();