Corrected bug whereby multiple override calls would clear __super too early
Before this change, __super was set to undefined. However, consider that we have two method overrides---foo and bar---and the code for bar is: this.foo(); this.__super(); foo() would set __super to undefined and so bar cannot invoke its super method unless it stores a reference to __super before invoking foo(). This patch fixes this issue.perfodd
parent
ae172a7a34
commit
daae0c6843
|
@ -34,17 +34,18 @@ exports.standard = {
|
||||||
retval = undefined
|
retval = undefined
|
||||||
;
|
;
|
||||||
|
|
||||||
// the _super property will contain the parent method (we don't
|
// the _super property will contain the parent method (store the
|
||||||
// store the previous value for performance reasons and because,
|
// previous value to ensure that calls to multiple overrides will
|
||||||
// during conventional use, it's completely unnecessary)
|
// be supported)
|
||||||
|
var psup = context.__super;
|
||||||
context.__super = super_method;
|
context.__super = super_method;
|
||||||
|
|
||||||
retval = method.apply( context, arguments );
|
retval = method.apply( context, arguments );
|
||||||
|
|
||||||
// prevent sneaky bastards from breaking encapsulation by stealing
|
// prevent sneaky bastards from breaking encapsulation by stealing
|
||||||
// method references (we set to undefined rather than deleting it
|
// method references and ensure that __super is properly restored
|
||||||
// because deletion causes performance degradation within V8)
|
// for nested/multiple override invocations
|
||||||
context.__super = undefined;
|
context.__super = psup;
|
||||||
|
|
||||||
// if the value returned from the method was the context that we
|
// if the value returned from the method was the context that we
|
||||||
// passed in, return the actual instance (to ensure we do not break
|
// passed in, return the actual instance (to ensure we do not break
|
||||||
|
|
|
@ -29,6 +29,7 @@ var common = require( './common' ),
|
||||||
// get in the way of our assertions
|
// get in the way of our assertions
|
||||||
hitMethod = false,
|
hitMethod = false,
|
||||||
hitMethod2 = false,
|
hitMethod2 = false,
|
||||||
|
hitDouble = false,
|
||||||
method2Arg = null,
|
method2Arg = null,
|
||||||
|
|
||||||
Foo = Class.extend(
|
Foo = Class.extend(
|
||||||
|
@ -46,6 +47,11 @@ var common = require( './common' ),
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'virtual double': function()
|
||||||
|
{
|
||||||
|
hitDouble = true;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
SubFoo = Foo.extend(
|
SubFoo = Foo.extend(
|
||||||
|
@ -59,6 +65,14 @@ var common = require( './common' ),
|
||||||
{
|
{
|
||||||
return this.__super( arg );
|
return this.__super( arg );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'override double': function()
|
||||||
|
{
|
||||||
|
this.myMethod();
|
||||||
|
this.__super();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
foo = new Foo(),
|
foo = new Foo(),
|
||||||
|
@ -81,7 +95,7 @@ assert.equal(
|
||||||
hitMethod = hitMethod2 = false;
|
hitMethod = hitMethod2 = false;
|
||||||
|
|
||||||
var arg = 'foobar';
|
var arg = 'foobar';
|
||||||
sub_foo.myMethod().myMethod2( arg );
|
sub_foo.myMethod().myMethod2( arg ).double();
|
||||||
|
|
||||||
// myMethod overrides without calling parent
|
// myMethod overrides without calling parent
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -112,3 +126,9 @@ assert['throws']( function()
|
||||||
});
|
});
|
||||||
}, TypeError, "Methods must be overridden with a Function" );
|
}, TypeError, "Methods must be overridden with a Function" );
|
||||||
|
|
||||||
|
// ensure that __super is not cleared after a call to an override
|
||||||
|
assert.equal(
|
||||||
|
hitDouble,
|
||||||
|
true,
|
||||||
|
"__super is maintained in a stack-like manner"
|
||||||
|
);
|
||||||
|
|
Loading…
Reference in New Issue