From 4f6073f2836f423e10fc7a24cda33ea9b010d45e Mon Sep 17 00:00:00 2001 From: Chris Connelly Date: Thu, 19 Jan 2017 21:46:42 +0000 Subject: [PATCH] Fix scope of assignments in dynamic class keys Dynamic class keys were using the method scope for compilation, resulting in missing declarations and runtime errors. --- lib/coffee-script/nodes.js | 4 +++- src/nodes.coffee | 2 ++ test/classes.coffee | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/coffee-script/nodes.js b/lib/coffee-script/nodes.js index 60a3c8ab26..61a1b79d0a 100644 --- a/lib/coffee-script/nodes.js +++ b/lib/coffee-script/nodes.js @@ -2782,7 +2782,7 @@ } compileNode(o) { - var answer, body, condition, exprs, haveSplatParam, i, ifTrue, j, k, len1, len2, m, modifiers, name, param, paramNames, params, paramsAfterSplat, ref, ref3, ref4, ref5, ref6, ref7, signature, splatParamName, thisAssignments, val, wasEmpty; + var answer, body, condition, exprs, haveSplatParam, i, ifTrue, j, k, len1, len2, m, methodScope, modifiers, name, param, paramNames, params, paramsAfterSplat, ref, ref3, ref4, ref5, ref6, ref7, ref8, signature, splatParamName, thisAssignments, val, wasEmpty; if (this.ctor) { if (this.isAsync) { this.variable.error('Class constructor may not be async'); @@ -2928,10 +2928,12 @@ body = this.body.compileWithDeclarations(o); } if (this.isMethod) { + ref8 = [o.scope, o.scope.parent], methodScope = ref8[0], o.scope = ref8[1]; name = this.name.compileToFragments(o); if (name[0].code === '.') { name.shift(); } + o.scope = methodScope; } answer = this.joinFragmentArrays((function() { var l, len3, results; diff --git a/src/nodes.coffee b/src/nodes.coffee index 9e722b0f6b..7b71c30db5 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -2009,8 +2009,10 @@ exports.Code = class Code extends Base # We need to compile the body before method names to ensure super references are handled if @isMethod + [methodScope, o.scope] = [o.scope, o.scope.parent] name = @name.compileToFragments o name.shift() if name[0].code is '.' + o.scope = methodScope answer = @joinFragmentArrays (@makeCode m for m in modifiers), ' ' answer.push @makeCode ' ' if modifiers.length and name diff --git a/test/classes.coffee b/test/classes.coffee index beb3a45420..9d8ed72c08 100644 --- a/test/classes.coffee +++ b/test/classes.coffee @@ -845,6 +845,22 @@ test "#1392 calling `super` in methods defined on namespaced classes", -> @a::m = -> super eq 5, (new C.a).m() + +test "dynamic method names", -> + class A + "#{name = 'm'}": -> 1 + eq 1, new A().m() + + class B extends A + "#{name = 'm'}": -> super + eq 1, new B().m() + + getName = -> 'm' + class C + "#{name = getName()}": -> 1 + eq 1, new C().m() + + test "dynamic method names and super", -> class Base @m: -> 6