Initial concept for protected static property access
parent
9067bbf0cf
commit
9b20cdff48
|
@ -52,6 +52,15 @@ var util = require( __dirname + '/util' ),
|
||||||
*/
|
*/
|
||||||
extending = false,
|
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
|
* Hash of reserved members
|
||||||
*
|
*
|
||||||
|
@ -619,6 +628,19 @@ function initStaticVisibilityObj( ctor, static_members )
|
||||||
// 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
|
||||||
ctor.___$$svis$$ = sobji;
|
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
|
// we use hasOwnProperty to ensure that undefined values will not
|
||||||
// cause us to continue checking the parent, thereby potentially
|
// cause us to continue checking the parent, thereby potentially
|
||||||
// failing to set perfectly legal values
|
// failing to set perfectly legal values
|
||||||
var has = Object.prototype.hasOwnProperty.call(
|
var has = Object.prototype.hasOwnProperty,
|
||||||
props[ 'public' ], prop
|
found = false,
|
||||||
),
|
|
||||||
|
|
||||||
// Determine if we were invoked in the context of a class. If
|
// Determine if we were invoked in the context of a class. If
|
||||||
// so, use that. Otherwise, use ourself.
|
// so, use that. Otherwise, use ourself.
|
||||||
context = ( this.___$$sprops$$ ) ? this : ctor
|
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 we don't own the property, let the parent(s) handle it
|
||||||
if ( !has )
|
if ( found === false )
|
||||||
{
|
{
|
||||||
return base.$.apply( context, arguments );
|
return base.$.apply( context, arguments );
|
||||||
}
|
}
|
||||||
|
@ -686,13 +717,13 @@ function attachStatic( ctor, members, base, inheriting )
|
||||||
// arguments.length to ensure that setting to undefined works)
|
// arguments.length to ensure that setting to undefined works)
|
||||||
if ( arguments.length > 1 )
|
if ( arguments.length > 1 )
|
||||||
{
|
{
|
||||||
props[ 'public' ][ prop ] = val;
|
props[ found ][ prop ] = val;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// return the value
|
// return the value
|
||||||
return props[ 'public' ][ prop ];
|
return props[ found ][ prop ];
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,6 +464,9 @@ var common = require( './common' ),
|
||||||
var val = 'foo',
|
var val = 'foo',
|
||||||
Foo = builder.build(
|
Foo = builder.build(
|
||||||
{
|
{
|
||||||
|
'protected static prop': val,
|
||||||
|
|
||||||
|
|
||||||
// the same rules should apply to methods
|
// the same rules should apply to methods
|
||||||
'protected static baz': function()
|
'protected static baz': function()
|
||||||
{
|
{
|
||||||
|
@ -481,6 +484,16 @@ var common = require( './common' ),
|
||||||
{
|
{
|
||||||
return this.__self.baz();
|
return this.__self.baz();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'public static staticGetProp': function()
|
||||||
|
{
|
||||||
|
return this.$('prop');
|
||||||
|
},
|
||||||
|
|
||||||
|
'public instGetProp': function()
|
||||||
|
{
|
||||||
|
return this.__self.$('prop');
|
||||||
|
},
|
||||||
} );
|
} );
|
||||||
|
|
||||||
assert.equal( Foo.baz, undefined,
|
assert.equal( Foo.baz, undefined,
|
||||||
|
@ -494,6 +507,14 @@ var common = require( './common' ),
|
||||||
assert.equal( Foo().instBaz(), val,
|
assert.equal( Foo().instBaz(), val,
|
||||||
"Protected methods are accessible to instance methods"
|
"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',
|
val2 = 'bazbaz',
|
||||||
Foo = builder.build(
|
Foo = builder.build(
|
||||||
{
|
{
|
||||||
|
'protected static prop': val,
|
||||||
|
|
||||||
'protected static foo': function()
|
'protected static foo': function()
|
||||||
{
|
{
|
||||||
return val;
|
return val;
|
||||||
|
@ -529,6 +552,11 @@ var common = require( './common' ),
|
||||||
{
|
{
|
||||||
return this.foo2();
|
return this.foo2();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'public static getProp': function()
|
||||||
|
{
|
||||||
|
return this.$('prop');
|
||||||
|
},
|
||||||
} ),
|
} ),
|
||||||
|
|
||||||
SubSubFoo = builder.build( SubFoo, {} )
|
SubSubFoo = builder.build( SubFoo, {} )
|
||||||
|
@ -546,6 +574,14 @@ var common = require( './common' ),
|
||||||
assert.equal( SubSubFoo.bar(), val,
|
assert.equal( SubSubFoo.bar(), val,
|
||||||
"Sub-subtypes inherit parents' protected static methods"
|
"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