1
0
Fork 0

Initial concept for protected static property access

closure/master
Mike Gerwitz 2011-05-12 00:05:50 -04:00
parent 9067bbf0cf
commit 9b20cdff48
2 changed files with 73 additions and 6 deletions

View File

@ -52,6 +52,15 @@ var util = require( __dirname + '/util' ),
*/
extending = false,
/**
* A flag to let the system know that we are currently attempting to access
* a static property from within a method. This means that the caller should
* be given access to additional levels of visibility.
*
* @type {boolean}
*/
sprop_internal = false,
/**
* Hash of reserved members
*
@ -619,6 +628,19 @@ function initStaticVisibilityObj( ctor, static_members )
// override __self on the instance's visibility object, giving internal
// methods access to the restricted static methods
ctor.___$$svis$$ = sobji;
// Override the class-level accessor method to allow the system to know we
// are within a method. An internal flag is necessary, rather than using an
// argument or binding, because those two options are exploitable. An
// internal flag cannot be modified by conventional means.
sobji.$ = function()
{
sprop_internal = true;
var val = ctor.$.apply( ctor, arguments );
sprop_internal = false;
return val;
};
}
@ -666,17 +688,26 @@ function attachStatic( ctor, members, base, inheriting )
// we use hasOwnProperty to ensure that undefined values will not
// cause us to continue checking the parent, thereby potentially
// failing to set perfectly legal values
var has = Object.prototype.hasOwnProperty.call(
props[ 'public' ], prop
),
var has = Object.prototype.hasOwnProperty,
found = false,
// Determine if we were invoked in the context of a class. If
// so, use that. Otherwise, use ourself.
context = ( this.___$$sprops$$ ) ? this : ctor
;
// Attempt to locate the property. First, we check public. If not
// available and we are internal (within a method), we can move on
// to check other levels of visibility. `found` will contain the
// visibility level the property was found in, or false.
found = has.call( props[ 'public' ], prop ) && 'public';
if ( !found && sprop_internal )
{
found = has.call( props[ 'protected' ], prop ) && 'protected';
}
// if we don't own the property, let the parent(s) handle it
if ( !has )
if ( found === false )
{
return base.$.apply( context, arguments );
}
@ -686,13 +717,13 @@ function attachStatic( ctor, members, base, inheriting )
// arguments.length to ensure that setting to undefined works)
if ( arguments.length > 1 )
{
props[ 'public' ][ prop ] = val;
props[ found ][ prop ] = val;
return context;
}
else
{
// return the value
return props[ 'public' ][ prop ];
return props[ found ][ prop ];
}
} );
}

View File

@ -464,6 +464,9 @@ var common = require( './common' ),
var val = 'foo',
Foo = builder.build(
{
'protected static prop': val,
// the same rules should apply to methods
'protected static baz': function()
{
@ -481,6 +484,16 @@ var common = require( './common' ),
{
return this.__self.baz();
},
'public static staticGetProp': function()
{
return this.$('prop');
},
'public instGetProp': function()
{
return this.__self.$('prop');
},
} );
assert.equal( Foo.baz, undefined,
@ -494,6 +507,14 @@ var common = require( './common' ),
assert.equal( Foo().instBaz(), val,
"Protected methods are accessible to instance methods"
);
assert.equal( Foo.staticGetProp(), val,
"Protected static properties are accessible to static methods"
);
assert.equal( Foo().instGetProp(), val,
"Protected static properties are accessible to instance methods"
);
} )();
@ -507,6 +528,8 @@ var common = require( './common' ),
val2 = 'bazbaz',
Foo = builder.build(
{
'protected static prop': val,
'protected static foo': function()
{
return val;
@ -529,6 +552,11 @@ var common = require( './common' ),
{
return this.foo2();
},
'public static getProp': function()
{
return this.$('prop');
},
} ),
SubSubFoo = builder.build( SubFoo, {} )
@ -546,6 +574,14 @@ var common = require( './common' ),
assert.equal( SubSubFoo.bar(), val,
"Sub-subtypes inherit parents' protected static methods"
);
assert.equal( SubFoo.getProp(), val,
"Subtypes inherit parents' protected static properties"
);
assert.equal( SubSubFoo.getProp(), val,
"Sub-subtypes inherit parents' protected static properties"
);
} )();