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 ); 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.prototype = prototype;
new_class.constructor = new_class; new_class.constructor = new_class;
@ -533,13 +534,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 {function() ctor class
* @param {number} cid class id
* *
* @return {undefined} * @return {undefined}
*/ */
function attachPropInit( prototype, properties, members, static_members, cid ) function attachPropInit( prototype, properties, members, ctor, cid )
{ {
util.defineSecureProp( prototype, '__initProps', function( inherit ) 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 // 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 // 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
@ -592,26 +593,25 @@ function attachPropInit( prototype, properties, members, static_members, cid )
/** /**
* Creates and populates the static visibility object * 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 * @param {{public: Object, protected: Object, private: Object}} static_members
* *
* @return {undefined} * @return {undefined}
*/ */
function initStaticVisibilityObj( vis, static_members ) function initStaticVisibilityObj( ctor, static_members )
{ {
// the object will simply be another layer in the prototype chain to // the object will simply be another layer in the prototype chain to
// prevent protected/private members from being mixed in with the public // prevent protected/private members from being mixed in with the public
var sobj = function() {}; var sobj = function() {};
sobj.prototype = this; sobj.prototype = ctor;
var sobji = new sobj(); var sobji = new sobj();
util.copyTo( sobji, static_members.methods[ 'protected' ] ); util.copyTo( sobji, static_members.methods[ 'protected' ] );
// override __self on the instance's visibility object, giving internal // override __self on the instance's visibility object, giving internal
// methods access to the restricted static methods // methods access to the restricted static methods
vis.__self = sobji; ctor.___$$svis$$ = sobji;
} }
@ -842,7 +842,9 @@ function getMethodInstance( inst, cid )
return ( iid && data ) return ( iid && data )
? data[ cid ] ? data[ cid ]
: null : ( inst.___$$svis$$ )
? inst.___$$svis$$
: null
; ;
} }

View File

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