1
0
Fork 0

Implemented protected static members within static methods

- Still not inheritence
closure/master
Mike Gerwitz 2011-05-10 19:54:23 -04:00
parent a246dd67e0
commit 3c774a7b16
2 changed files with 35 additions and 20 deletions

View File

@ -234,7 +234,8 @@ exports.build = function extend()
}
staticInit( new_class, false );
attachPropInit( prototype, prop_init, members, static_members, class_id );
initStaticVisibilityObj( new_class, static_members );
attachPropInit( prototype, prop_init, members, new_class, class_id );
new_class.prototype = prototype;
new_class.constructor = new_class;
@ -533,13 +534,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 {function() ctor class
* @param {number} cid class id
*
* @return {undefined}
*/
function attachPropInit( prototype, properties, members, static_members, cid )
function attachPropInit( prototype, properties, members, ctor, cid )
{
util.defineSecureProp( prototype, '__initProps', function( inherit )
{
@ -575,7 +576,7 @@ function attachPropInit( prototype, properties, members, static_members, cid )
);
// give internal methods access to protected/private static members
initStaticVisibilityObj.call( this, vis, static_members );
vis.__self = ctor.___$$svis$$;
// provide a means to access the actual instance (rather than the
// property/visibility object) internally (this will translate to
@ -592,26 +593,25 @@ function attachPropInit( prototype, properties, members, static_members, cid )
/**
* Creates and populates the static visibility object
*
* This function should be called in the context of the class.
* @param {function()} 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 )
function initStaticVisibilityObj( ctor, 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;
sobj.prototype = ctor;
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;
ctor.___$$svis$$ = sobji;
}
@ -842,6 +842,8 @@ function getMethodInstance( inst, cid )
return ( iid && data )
? data[ cid ]
: ( inst.___$$svis$$ )
? inst.___$$svis$$
: null
;
}

View File

@ -35,7 +35,8 @@ var common = require( './common' ),
*/
( function testSelfPropertyReferencesClassDefinition()
{
var Foo = builder.build(
var val = [ 'baz' ],
Foo = builder.build(
{
'public function test': function()
{
@ -43,9 +44,11 @@ var common = require( './common' ),
},
} );
Foo.bar = val;
// we must use instanceof here because the __self object has the class in
// its prototype chain
assert.ok( Foo().test() instanceof Foo,
assert.ok( ( Foo().test().bar === Foo.bar ),
"__self property references class definition"
);
} )();
@ -198,7 +201,7 @@ var common = require( './common' ),
* available for an instance, it falls back. This serves as a regression test to
* ensure this functionality remains.
*/
( function testStaticMethodsBoundToClassRatherThanInstance()
( function testStaticMethodsNotBoundToInstance()
{
var result = null,
Foo = builder.build(
@ -212,7 +215,7 @@ var common = require( './common' ),
// call the static method
Foo.foo();
assert.deepEqual( result, Foo,
assert.notEqual( result, Foo,
"Static members are bound to class definition rather than instance"
);
} )();
@ -445,6 +448,12 @@ var common = require( './common' ),
return val;
},
// ensure method is accessible to static methods
'public static staticBaz': function()
{
return this.baz();
},
// ensure method is accessible to instance methods
'public instBaz': function()
{
@ -456,6 +465,10 @@ var common = require( './common' ),
"Protected methods should not be accessible outside the class"
);
assert.equal( Foo.staticBaz(), val,
"Protected methods are accessible to static methods"
);
assert.equal( Foo().instBaz(), val,
"Protected methods are accessible to instance methods"
);