Fix for overriding protected with protected
- A better solution may be exploredclosure/master
parent
71c9f6cabe
commit
63a4f95f65
|
@ -145,6 +145,9 @@ exports.buildMethod = function(
|
||||||
// to ensure privileged calls will work properly
|
// to ensure privileged calls will work properly
|
||||||
dest[ name ] = overrideMethod( value, null, instCallback, cid );
|
dest[ name ] = overrideMethod( value, null, instCallback, cid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store keywords for later reference (needed for pre-ES5 fallback)
|
||||||
|
dest[ name ].___$$keywords$$ = keywords;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,11 @@ exports.setup = function( dest, properties, methods )
|
||||||
// public. The reason for this is because the property object is laid /atop/
|
// public. The reason for this is because the property object is laid /atop/
|
||||||
// of the public members, meaning that a parent's protected members will
|
// of the public members, meaning that a parent's protected members will
|
||||||
// take precedence over a subtype's overriding /public/ members. Uh oh.
|
// take precedence over a subtype's overriding /public/ members. Uh oh.
|
||||||
doSetup( dest, properties[ 'protected' ], methods[ 'protected' ], true );
|
doSetup( dest,
|
||||||
|
properties[ 'protected' ],
|
||||||
|
methods[ 'protected' ],
|
||||||
|
'public'
|
||||||
|
);
|
||||||
|
|
||||||
// then add the private parts
|
// then add the private parts
|
||||||
doSetup( obj, properties[ 'private' ], methods[ 'private' ] );
|
doSetup( obj, properties[ 'private' ], methods[ 'private' ] );
|
||||||
|
@ -90,11 +94,10 @@ exports.setup = function( dest, properties, methods )
|
||||||
*
|
*
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
function doSetup( dest, properties, methods, unless_exists )
|
function doSetup( dest, properties, methods, unless_keyword )
|
||||||
{
|
{
|
||||||
unless_exists = !!unless_exists;
|
var hasOwn = Array.prototype.hasOwnProperty,
|
||||||
|
pre = null;
|
||||||
var hasOwn = Array.prototype.hasOwnProperty;
|
|
||||||
|
|
||||||
// copy over the methods
|
// copy over the methods
|
||||||
if ( methods !== undefined )
|
if ( methods !== undefined )
|
||||||
|
@ -103,13 +106,24 @@ function doSetup( dest, properties, methods, unless_exists )
|
||||||
{
|
{
|
||||||
if ( hasOwn.call( methods, method_name ) )
|
if ( hasOwn.call( methods, method_name ) )
|
||||||
{
|
{
|
||||||
|
pre = dest[ method_name ];
|
||||||
|
|
||||||
// If requested, do not copy the method over if it already
|
// If requested, do not copy the method over if it already
|
||||||
// exists in the destination object. Don't use hasOwn here;
|
// exists in the destination object. Don't use hasOwn here;
|
||||||
// unnecessary overhead and we want to traverse any prototype
|
// unnecessary overhead and we want to traverse any prototype
|
||||||
// chains. We do not check the public object directly, for
|
// chains. We do not check the public object directly, for
|
||||||
// example, because we need a solution that will work if a proxy
|
// example, because we need a solution that will work if a proxy
|
||||||
// is unsupported by the engine.
|
// is unsupported by the engine.
|
||||||
if ( !unless_exists || ( dest[ method_name ] === undefined ) )
|
//
|
||||||
|
// Also note that we need to allow overriding if it exists in
|
||||||
|
// the protected object (we can override protected with
|
||||||
|
// protected). This is the *last* check to ensure a performance
|
||||||
|
// hit is incured *only* if we're overriding protected with
|
||||||
|
// protected.
|
||||||
|
if ( !unless_keyword
|
||||||
|
|| ( pre === undefined )
|
||||||
|
|| !( pre.___$$keywords$$[ unless_keyword ] )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
dest[ method_name ] = methods[ method_name ];
|
dest[ method_name ] = methods[ method_name ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -725,3 +725,41 @@ var common = require( './common' ),
|
||||||
);
|
);
|
||||||
} )();
|
} )();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There was a bug introduced when we prevented protected members from
|
||||||
|
* overriding public (since in the prototype chain, protected members are laid
|
||||||
|
* atop public, and this cannot change). This bug would disallow protected
|
||||||
|
* members from being overridden by other protected members.
|
||||||
|
*
|
||||||
|
* This test is both a proof and a regression test.
|
||||||
|
*/
|
||||||
|
( function testCanProperlyOverrideProtectedWithProtected()
|
||||||
|
{
|
||||||
|
var val = 'foobar',
|
||||||
|
result = Class(
|
||||||
|
{
|
||||||
|
'protected foo': function() {},
|
||||||
|
} ).extend(
|
||||||
|
{
|
||||||
|
// provide concrete implementation
|
||||||
|
'protected foo': function()
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
|
||||||
|
'public doFoo': function()
|
||||||
|
{
|
||||||
|
return this.foo();
|
||||||
|
},
|
||||||
|
} )().doFoo();
|
||||||
|
;
|
||||||
|
|
||||||
|
// if everything worked as expected, the value of 'val' will have been
|
||||||
|
// returned and stored in 'result'
|
||||||
|
assert.equal( result, val,
|
||||||
|
"Protected methods can properly be overriden by another protected " +
|
||||||
|
"method"
|
||||||
|
);
|
||||||
|
} )();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue