1
0
Fork 0

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
Mike Gerwitz 2013-04-20 21:54:29 -04:00
parent ae172a7a34
commit daae0c6843
No known key found for this signature in database
GPG Key ID: F22BB8158EE30EAB
2 changed files with 28 additions and 7 deletions

View File

@ -34,17 +34,18 @@ exports.standard = {
retval = undefined
;
// the _super property will contain the parent method (we don't
// store the previous value for performance reasons and because,
// during conventional use, it's completely unnecessary)
// the _super property will contain the parent method (store the
// previous value to ensure that calls to multiple overrides will
// be supported)
var psup = context.__super;
context.__super = super_method;
retval = method.apply( context, arguments );
// prevent sneaky bastards from breaking encapsulation by stealing
// method references (we set to undefined rather than deleting it
// because deletion causes performance degradation within V8)
context.__super = undefined;
// method references and ensure that __super is properly restored
// for nested/multiple override invocations
context.__super = psup;
// if the value returned from the method was the context that we
// passed in, return the actual instance (to ensure we do not break

View File

@ -29,6 +29,7 @@ var common = require( './common' ),
// get in the way of our assertions
hitMethod = false,
hitMethod2 = false,
hitDouble = false,
method2Arg = null,
Foo = Class.extend(
@ -46,6 +47,11 @@ var common = require( './common' ),
return this;
},
'virtual double': function()
{
hitDouble = true;
}
}),
SubFoo = Foo.extend(
@ -59,6 +65,14 @@ var common = require( './common' ),
{
return this.__super( arg );
},
'override double': function()
{
this.myMethod();
this.__super();
return this;
}
}),
foo = new Foo(),
@ -81,7 +95,7 @@ assert.equal(
hitMethod = hitMethod2 = false;
var arg = 'foobar';
sub_foo.myMethod().myMethod2( arg );
sub_foo.myMethod().myMethod2( arg ).double();
// myMethod overrides without calling parent
assert.equal(
@ -112,3 +126,9 @@ assert['throws']( 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"
);