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:
parent
60c9b94656
commit
5542e00b80
5 changed files with 61 additions and 8 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 """
|
||||
|
|
|
@ -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) ->
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue