Writes to public static properties now work properly
parent
44cd8db82d
commit
e3c526b89d
|
@ -614,13 +614,34 @@ function attachStatic( ctor, members, base, inheriting )
|
|||
{
|
||||
ctor.___$$sprops$$ = props;
|
||||
|
||||
ctor.$ = function( prop )
|
||||
// provide a method to access static properties
|
||||
ctor.$ = function( prop, val )
|
||||
{
|
||||
// attempt to return property if it is our own, otherwise look up on
|
||||
// parent (the parent will look up its parent as well, if necessary)
|
||||
return props[ 'public' ][ prop ]
|
||||
|| base.$( prop )
|
||||
;
|
||||
// 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
|
||||
);
|
||||
|
||||
// if we don't own the property, let the parent(s) handle it
|
||||
if ( !has )
|
||||
{
|
||||
return base.$.apply( this, arguments );
|
||||
}
|
||||
|
||||
// if a value was provided, this method should be treated as a
|
||||
// setter rather than a getter
|
||||
if ( val )
|
||||
{
|
||||
props[ 'public' ][ prop ] = val;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// return the value
|
||||
return props[ 'public' ][ prop ];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -309,6 +309,8 @@ var common = require( './common' ),
|
|||
( function testPublicStaticPropertyReferencesAreInheritedBySubtypes()
|
||||
{
|
||||
var val = [ 1, 2, 3 ],
|
||||
val2 = [ 'a', 'b', 'c' ],
|
||||
|
||||
Foo = builder.build(
|
||||
{
|
||||
'public static bar': val,
|
||||
|
@ -320,5 +322,51 @@ var common = require( './common' ),
|
|||
assert.ok( SubFoo.$('bar') === Foo.$('bar'),
|
||||
"Inherited static properties should share references"
|
||||
);
|
||||
|
||||
// setting a property on Foo should set the property on SubFoo and
|
||||
// vice-versa
|
||||
Foo.$( 'bar', val2 );
|
||||
assert.deepEqual( Foo.$( 'bar' ), val2,
|
||||
"Can set static property values"
|
||||
);
|
||||
|
||||
assert.ok( Foo.$( 'bar' ) === SubFoo.$( 'bar' ),
|
||||
"Setting a static property value on a supertype also sets the value " +
|
||||
"on subtypes"
|
||||
);
|
||||
|
||||
SubFoo.$( 'bar', val );
|
||||
assert.ok( Foo.$( 'bar' ) === SubFoo.$( 'bar' ) );
|
||||
} )();
|
||||
|
||||
|
||||
/**
|
||||
* Static members do not have the benefit of prototype chains. We must
|
||||
* implement our own means of traversing the inheritance tree. This is done by
|
||||
* checking to see if a class has defined the requested property, then
|
||||
* forwarding the call to the parent if it has not.
|
||||
*
|
||||
* The process of looking up the property is very important. hasOwnProperty is
|
||||
* used rather than checking for undefined, because they have drastically
|
||||
* different results. Setting a value to undefined (if hasOwnProperty were not
|
||||
* used) would effectively forward all requests to the base class (since no
|
||||
* property would be found), thereby preventing it from ever being written to
|
||||
* again.
|
||||
*/
|
||||
( function testSettingsStaticPropertiesToUndefinedWillNotCorruptLookupProcess()
|
||||
{
|
||||
var val = 'baz',
|
||||
Foo = builder.build(
|
||||
{
|
||||
'public static foo': '',
|
||||
} )
|
||||
;
|
||||
|
||||
Foo.$( 'foo', undefined );
|
||||
Foo.$( 'foo', val );
|
||||
|
||||
assert.equal( Foo.$( 'foo' ), val,
|
||||
"Setting static property to undefined does not corrupt lookup process"
|
||||
);
|
||||
} )();
|
||||
|
||||
|
|
Loading…
Reference in New Issue