diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 31b2f295..bced2670 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -210,7 +210,8 @@ module CoffeeScript def compile_super(args, o) methname = o[:last_assign].sub(LEADING_DOT, '') - "this.constructor.prototype.#{methname}.call(this, #{args})" + arg_part = args.empty? ? '' : ", #{args}" + "#{o[:proto_assign]}.prototype.__proto__.#{methname}.call(this#{arg_part})" end end @@ -299,7 +300,8 @@ module CoffeeScript # Setting the value of a local variable, or the value of an object property. class AssignNode < Node - LEADING_VAR = /\Avar\s+/ + LEADING_VAR = /\Avar\s+/ + PROTO_ASSIGN = /\A(\S+)\.prototype/ statement custom_return @@ -316,9 +318,10 @@ module CoffeeScript def compile(o={}) o = super(o) - name = @variable.respond_to?(:compile) ? @variable.compile(o) : @variable + name = @variable.respond_to?(:compile) ? @variable.compile(o) : @variable.to_s last = @variable.respond_to?(:last) ? @variable.last.to_s : name.to_s - o = o.merge(:assign => name, :last_assign => last) + proto = name[PROTO_ASSIGN, 1] + o = o.merge(:assign => name, :last_assign => last, :proto_assign => proto) postfix = o[:return] ? ";\n#{o[:indent]}return #{name}" : '' return write("#{@variable}: #{@value.compile(o)}") if @context == :object return write("#{name} = #{@value.compile(o)}#{postfix}") if @variable.properties? && !@value.custom_assign? diff --git a/test/fixtures/execution/calling_super.cs b/test/fixtures/execution/calling_super.cs new file mode 100644 index 00000000..e729db1e --- /dev/null +++ b/test/fixtures/execution/calling_super.cs @@ -0,0 +1,23 @@ +Base: => . +Base.prototype.func: string => + 'zero/' + string. + +FirstChild: => . +FirstChild.prototype.__proto__: new Base() +FirstChild.prototype.func: string => + super('one/') + string. + +SecondChild: => . +SecondChild.prototype.__proto__: new FirstChild() +SecondChild.prototype.func: string => + super('two/') + string. + +ThirdChild: => . +ThirdChild.prototype.__proto__: new SecondChild() +ThirdChild.prototype.func: string => + super('three/') + string. + +result: (new ThirdChild()).func('four') + +print(result is 'zero/one/two/three/four') + diff --git a/test/fixtures/execution/calling_super.js b/test/fixtures/execution/calling_super.js new file mode 100644 index 00000000..dfd3d99a --- /dev/null +++ b/test/fixtures/execution/calling_super.js @@ -0,0 +1,27 @@ +(function(){ + var Base = function() { + }; + Base.prototype.func = function(string) { + return 'zero/' + string; + }; + var FirstChild = function() { + }; + FirstChild.prototype.__proto__ = new Base(); + FirstChild.prototype.func = function(string) { + return FirstChild.prototype.__proto__.func.call(this, 'one/') + string; + }; + var SecondChild = function() { + }; + SecondChild.prototype.__proto__ = new FirstChild(); + SecondChild.prototype.func = function(string) { + return SecondChild.prototype.__proto__.func.call(this, 'two/') + string; + }; + var ThirdChild = function() { + }; + ThirdChild.prototype.__proto__ = new SecondChild(); + ThirdChild.prototype.func = function(string) { + return ThirdChild.prototype.__proto__.func.call(this, 'three/') + string; + }; + var result = (new ThirdChild()).func('four'); + print(result === 'zero/one/two/three/four'); +})(); \ No newline at end of file