1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

sart work on a bugfix, but we're not covering the exact case in issue #1183

This commit is contained in:
Maxwell Krohn 2012-04-11 18:05:33 -04:00
parent 60c9b94656
commit 5542e00b80
5 changed files with 61 additions and 8 deletions

View file

@ -750,7 +750,7 @@
Call.prototype.superReference = function(o) {
var accesses, method, name;
method = o.scope.method;
method = o.scope.getMethodRecurse();
if (!method) {
throw SyntaxError('cannot call super outside of a function.');
}
@ -770,6 +770,15 @@
}
};
Call.prototype.superThis = function(o) {
var _ref2, _ref3;
if (((_ref2 = o.scope) != null ? (_ref3 = _ref2.method) != null ? _ref3.context : void 0 : void 0) != null) {
return o.scope.method.context;
} else {
return "this";
}
};
Call.prototype.unfoldSoak = function(o) {
var call, ifn, left, list, rite, _i, _len, _ref2, _ref3;
if (this.soak) {
@ -866,20 +875,20 @@
return _results;
})()).join(', ');
if (this.isSuper) {
return this.superReference(o) + (".call(this" + (args && ', ' + args) + ")");
return this.superReference(o) + (".call(" + (this.superThis(o)) + (args && ', ' + args) + ")");
} else {
return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")");
}
};
Call.prototype.compileSuper = function(args, o) {
return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")";
return "" + (this.superReference(o)) + ".call(" + (this.superThis(o)) + (args.length ? ', ' : '') + args + ")";
};
Call.prototype.compileSplat = function(o, splatArgs) {
var base, fun, idt, name, ref;
if (this.isSuper) {
return "" + (this.superReference(o)) + ".apply(this, " + splatArgs + ")";
return "" + (this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", " + splatArgs + ")";
}
if (this.isNew) {
idt = this.tab + TAB;

View file

@ -40,6 +40,17 @@
}
};
Scope.prototype.getMethodRecurse = function() {
var _ref1;
if (((_ref1 = this.method) != null ? _ref1.name : void 0) != null) {
return this.method;
} else if (this.parent) {
return this.parent.getMethodRecurse();
} else {
return {};
}
};
Scope.prototype.find = function(name, options) {
if (this.check(name, options)) {
return true;

View file

@ -496,7 +496,9 @@ exports.Call = class Call extends Base
# Grab the reference to the superclass's implementation of the current
# method.
superReference: (o) ->
{method} = o.scope
# keep walking up the scope chain until we find the original reference
# to a method. Stop at the first one.
method = o.scope.getMethodRecurse()
throw SyntaxError 'cannot call super outside of a function.' unless method
{name} = method
throw SyntaxError 'cannot call super on an anonymous function.' unless name?
@ -508,6 +510,9 @@ exports.Call = class Call extends Base
else
"#{name}.__super__.constructor"
superThis : (o) ->
if o.scope?.method?.context? then o.scope.method.context else "this"
# Soaked chained invocations unfold into if/else ternary structures.
unfoldSoak: (o) ->
if @soak
@ -566,21 +571,21 @@ exports.Call = class Call extends Base
args = @filterImplicitObjects @args
args = (arg.compile o, LEVEL_LIST for arg in args).join ', '
if @isSuper
@superReference(o) + ".call(this#{ args and ', ' + args })"
@superReference(o) + ".call(#{@superThis o}#{ args and ', ' + args })"
else
(if @isNew then 'new ' else '') + @variable.compile(o, LEVEL_ACCESS) + "(#{args})"
# `super()` is converted into a call against the superclass's implementation
# of the current function.
compileSuper: (args, o) ->
"#{@superReference(o)}.call(this#{ if args.length then ', ' else '' }#{args})"
"#{@superReference(o)}.call(#{@superThis o}#{ if args.length then ', ' else '' }#{args})"
# If you call a function with a splat, it's converted into a JavaScript
# `.apply()` call to allow an array of arguments to be passed.
# If it's a constructor, then things get real tricky. We have to inject an
# inner constructor in order to be able to pass the varargs.
compileSplat: (o, splatArgs) ->
return "#{ @superReference o }.apply(this, #{splatArgs})" if @isSuper
return "#{ @superReference o }.apply(#{@superThis o}, #{splatArgs})" if @isSuper
if @isNew
idt = @tab + TAB
return """

View file

@ -30,6 +30,11 @@ exports.Scope = class Scope
else
@positions[name] = @variables.push({name, type}) - 1
getMethodRecurse: ->
if @method?.name? then @method
else if @parent then @parent.getMethodRecurse()
else {}
# Look up a variable name in lexical scope, and declare it if it does not
# already exist.
find: (name, options) ->

View file

@ -41,3 +41,26 @@ test "#1973: redefining Array/Object constructors shouldn't confuse __X helpers"
obj = {arr}
for own k of obj
eq arr, obj[k]
test "super + fat arrows", ->
dolater = (cb) -> cb()
class A
constructor: ->
@_i = 0
foo : (cb) ->
dolater =>
@_i += 1
cb()
class B extends A
constructor : ->
super
foo : (cb) ->
dolater =>
dolater =>
@_i += 2
super cb
b = new B()
b.foo => eq b._i, 3