Initial concept for protected static property access
parent
9067bbf0cf
commit
9b20cdff48
|
@ -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 ];
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
} )();
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue