From b923d6dd527e0ff02e492898fa5612bf61894a02 Mon Sep 17 00:00:00 2001 From: Sam Stephenson Date: Sat, 18 Aug 2007 22:55:35 +0000 Subject: [PATCH] prototype: Fix superclass method call breakage from [7337]. --- CHANGELOG | 2 ++ src/base.js | 8 ++++---- test/unit/base.html | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 650e67c..aff192b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Fix superclass method call breakage from [7337]. [Mislav Marohnić, sam] + * Change Class.extend to allow for superclass method resolution and remove Class.inherit. Closes #9274. [Samuel Lebeau] * Event handlers are now bound to the observed element, not the event's target element. [Dan Webb] diff --git a/src/base.js b/src/base.js index c9728a1..9bb02ea 100644 --- a/src/base.js +++ b/src/base.js @@ -15,7 +15,7 @@ var Class = { klass.superclass = parent; klass.subclasses = []; - if (Object.isFunction(parent)) { + if (parent) { klass.prototype = new parent(extending); parent.subclasses.push(klass); } @@ -34,9 +34,9 @@ var Class = { var value = source[property]; if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") { - var method = value, value = Object.extend((function() { - return ancestor[property].apply(this, arguments) - }).wrap(method), { + var method = value, value = Object.extend((function(m) { + return function() { return ancestor[m].apply(this, arguments) }; + })(property).wrap(method), { valueOf: function() { return method }, toString: function() { return method.toString() } }); diff --git a/test/unit/base.html b/test/unit/base.html index 10f9e16..e530555 100644 --- a/test/unit/base.html +++ b/test/unit/base.html @@ -398,7 +398,20 @@ } }}, - testInstantiation: function() { with(this) { + testClassCreate: function() { with(this) { + assert(Object.isFunction(Animal), 'Animal is not a constructor'); + assertEnumEqual([Cat, Mouse], Animal.subclasses); + Animal.subclasses.each(function(subclass) { + assertEqual(Animal, subclass.superclass); + }); + + var Bird = Class.create(Animal); + assertEqual(Bird, Animal.subclasses.last()); + // for..in loop (for some reason) doesn't iterate over the constructor property in top-level classes + assertEnumEqual(Object.keys(new Animal), Object.keys(new Bird).without('constructor')); + }}, + + testClassInstantiation: function() { with(this) { var pet = new Animal("Nibbles"); assertEqual("Nibbles", pet.name, "property not initialized"); assertEqual('Nibbles: Hi!', pet.say('Hi!')); @@ -415,12 +428,29 @@ assertEqual('Tom: Yuk! I only eat mice.', tom.eat(new Animal)); }}, - testSupercall: function() { with(this) { + testSuperclassMethodCall: function() { with(this) { var tom = new Cat('Tom'); assertEqual('Tom: Yum!', tom.eat(new Mouse)); + + // augment the constructor and test + var Dodo = Class.create(Animal, { + initialize: function($super, name) { + $super(name); + this.extinct = true; + }, + + say: function($super, message) { + return $super(message) + " honk honk"; + } + }); + + var gonzo = new Dodo('Gonzo'); + assertEqual('Gonzo', gonzo.name); + assert(gonzo.extinct, 'Dodo birds should be extinct'); + assertEqual("Gonzo: hello honk honk", gonzo.say("hello")); }}, - testAddingInstanceMethod: function() { with(this) { + testClassExtend: function() { with(this) { var tom = new Cat('Tom'); var jerry = new Mouse('Jerry');