From 38f5963b85583e1229c0249def1bcdc6f4b9bdf7 Mon Sep 17 00:00:00 2001 From: Chris Connelly Date: Thu, 28 Dec 2017 22:50:12 +0000 Subject: [PATCH] Use free variables for anonymous classes (#4826) Fixes #4822. --- lib/coffeescript/nodes.js | 8 ++++---- src/nodes.coffee | 10 +++++----- test/classes.coffee | 7 +++++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/coffeescript/nodes.js b/lib/coffeescript/nodes.js index d636d27b0d..af9edf7928 100644 --- a/lib/coffeescript/nodes.js +++ b/lib/coffeescript/nodes.js @@ -2821,16 +2821,16 @@ if (argumentsNode = this.body.contains(isLiteralArguments)) { argumentsNode.error("Class bodies shouldn't reference arguments"); } - this.name = (ref1 = this.class.name) != null ? ref1 : this.defaultClassVariableName; - directives = this.walkBody(); - this.setContext(); - ident = new IdentifierLiteral(this.name); params = []; args = [new ThisLiteral]; wrapper = new Code(params, this.body); klass = new Parens(new Call(new Value(wrapper, [new Access(new PropertyName('call'))]), args)); this.body.spaced = true; o.classScope = wrapper.makeScope(o.scope); + this.name = (ref1 = this.class.name) != null ? ref1 : o.classScope.freeVariable(this.defaultClassVariableName); + ident = new IdentifierLiteral(this.name); + directives = this.walkBody(); + this.setContext(); if (this.class.hasNameClash) { parent = new IdentifierLiteral(o.classScope.freeVariable('superClass')); wrapper.params.push(new Param(parent)); diff --git a/src/nodes.coffee b/src/nodes.coffee index 90e93457b7..c5cc8f835b 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -1871,11 +1871,6 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base if argumentsNode = @body.contains isLiteralArguments argumentsNode.error "Class bodies shouldn't reference arguments" - @name = @class.name ? @defaultClassVariableName - directives = @walkBody() - @setContext() - - ident = new IdentifierLiteral @name params = [] args = [new ThisLiteral] wrapper = new Code params, @body @@ -1885,6 +1880,11 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base o.classScope = wrapper.makeScope o.scope + @name = @class.name ? o.classScope.freeVariable @defaultClassVariableName + ident = new IdentifierLiteral @name + directives = @walkBody() + @setContext() + if @class.hasNameClash parent = new IdentifierLiteral o.classScope.freeVariable 'superClass' wrapper.params.push new Param parent diff --git a/test/classes.coffee b/test/classes.coffee index 8168c08d58..d4df4fbeb1 100644 --- a/test/classes.coffee +++ b/test/classes.coffee @@ -1858,6 +1858,13 @@ test "#4724: backticked expression in a class body with hoisted member", -> eq 42, a.x eq 84, a.hoisted +test "#4822: nested anonymous classes use non-conflicting variable names", -> + Class = class + @a: class + @b: 1 + + eq Class.a.b, 1 + test "#4827: executable class body wrappers have correct context", -> test = -> class @A