From 148aa3f96d15e293d8ddc4074a8af6a1990b8dca Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 7 Apr 2015 11:32:33 +0200 Subject: [PATCH 1/2] Use a functionExpression with class decorators. Fixes #1161. --- .../transformers/es6/classes.js | 12 ++++++-- .../es7.decorators/class/actual.js | 7 +++++ .../es7.decorators/class/expected.js | 29 +++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index 1a63e8ad8b..f15233451b 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -30,7 +30,7 @@ var collectPropertyReferencesVisitor = { } if (this.isReferenced() && scope.getBinding(node.name) === state.scope.getBinding(node.name)) { - state.references[node.name] = true;; + state.references[node.name] = true; } } } @@ -140,7 +140,7 @@ class ClassTransformer { var constructorBody = this.constructorBody = t.blockStatement([]); var constructor; - if (this.className) { + if (this.className && !this.node.decorators) { constructor = t.functionDeclaration(this.className, [], constructorBody); body.push(constructor); } else { @@ -189,6 +189,14 @@ class ClassTransformer { } if (this.className) { + if (decorators) { + constructor = t.functionExpression(this.className, constructor.params, constructorBody); + + body.unshift(t.variableDeclaration("var", [ + t.variableDeclarator(classRef, constructor) + ])); + } + // named class with only a constructor if (body.length === 1) return t.toExpression(body[0]); } else { diff --git a/test/core/fixtures/transformation/es7.decorators/class/actual.js b/test/core/fixtures/transformation/es7.decorators/class/actual.js index d7af40351a..96ced15a45 100644 --- a/test/core/fixtures/transformation/es7.decorators/class/actual.js +++ b/test/core/fixtures/transformation/es7.decorators/class/actual.js @@ -12,3 +12,10 @@ var Foo2 = @bar class Foo { var Bar2 = @foo @bar class Bar { }; + +@foo +class Baz{ + constructor(baz) { + this.baz = baz; + } +} diff --git a/test/core/fixtures/transformation/es7.decorators/class/expected.js b/test/core/fixtures/transformation/es7.decorators/class/expected.js index cb9c85c166..d0388c5577 100644 --- a/test/core/fixtures/transformation/es7.decorators/class/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class/expected.js @@ -1,18 +1,18 @@ "use strict"; var Foo = (function () { - function Foo() { + var Foo = function Foo() { babelHelpers.classCallCheck(this, Foo); - } + }; Foo = foo(Foo) || Foo; return Foo; })(); var Bar = (function () { - function Bar() { + var Bar = function Bar() { babelHelpers.classCallCheck(this, Bar); - } + }; Bar = foo(Bar) || Bar; Bar = bar(Bar) || Bar; @@ -20,20 +20,31 @@ var Bar = (function () { })(); var Foo2 = (function () { - function Foo() { + var Foo = function Foo() { babelHelpers.classCallCheck(this, Foo); - } + }; Foo = bar(Foo) || Foo; return Foo; })(); var Bar2 = (function () { - function Bar() { + var Bar = function Bar() { babelHelpers.classCallCheck(this, Bar); - } + }; Bar = foo(Bar) || Bar; Bar = bar(Bar) || Bar; return Bar; -})(); \ No newline at end of file +})(); + +var Baz = (function () { + var Baz = function Baz(baz) { + babelHelpers.classCallCheck(this, Baz); + + this.baz = baz; + }; + + Baz = foo(Baz) || Baz; + return Baz; +})(); From 3987545b4f9bba35b85c55ccba2394916b5835cf Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 7 Apr 2015 14:15:26 +0200 Subject: [PATCH 2/2] Ensure correct scope for decorated classes. --- .../transformers/es6/classes.js | 26 ++++++++------ .../es7.decorators/class/expected.js | 35 +++++++++++-------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index f15233451b..9b33376ebf 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -140,7 +140,7 @@ class ClassTransformer { var constructorBody = this.constructorBody = t.blockStatement([]); var constructor; - if (this.className && !this.node.decorators) { + if (this.className) { constructor = t.functionDeclaration(this.className, [], constructorBody); body.push(constructor); } else { @@ -170,15 +170,27 @@ class ClassTransformer { this.buildBody(); + var decorators = this.node.decorators; + var classCheckRef = classRef; + + if (decorators) { + classCheckRef = this.scope.generateUidIdentifier(classRef); + } + constructorBody.body.unshift(t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [ t.thisExpression(), - classRef + classCheckRef ]))); // - var decorators = this.node.decorators; if (decorators) { + if (this.className) { + body.push(t.variableDeclaration("var", [ + t.variableDeclarator(classCheckRef, classRef) + ])); + } + for (var i = 0; i < decorators.length; i++) { var decorator = decorators[i]; body.push(util.template("class-decorator", { @@ -189,14 +201,6 @@ class ClassTransformer { } if (this.className) { - if (decorators) { - constructor = t.functionExpression(this.className, constructor.params, constructorBody); - - body.unshift(t.variableDeclaration("var", [ - t.variableDeclarator(classRef, constructor) - ])); - } - // named class with only a constructor if (body.length === 1) return t.toExpression(body[0]); } else { diff --git a/test/core/fixtures/transformation/es7.decorators/class/expected.js b/test/core/fixtures/transformation/es7.decorators/class/expected.js index d0388c5577..e60d87aba8 100644 --- a/test/core/fixtures/transformation/es7.decorators/class/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class/expected.js @@ -1,50 +1,55 @@ "use strict"; var Foo = (function () { - var Foo = function Foo() { - babelHelpers.classCallCheck(this, Foo); - }; + function Foo() { + babelHelpers.classCallCheck(this, _Foo); + } + var _Foo = Foo; Foo = foo(Foo) || Foo; return Foo; })(); var Bar = (function () { - var Bar = function Bar() { - babelHelpers.classCallCheck(this, Bar); - }; + function Bar() { + babelHelpers.classCallCheck(this, _Bar); + } + var _Bar = Bar; Bar = foo(Bar) || Bar; Bar = bar(Bar) || Bar; return Bar; })(); var Foo2 = (function () { - var Foo = function Foo() { - babelHelpers.classCallCheck(this, Foo); - }; + function Foo() { + babelHelpers.classCallCheck(this, _Foo2); + } + var _Foo2 = Foo; Foo = bar(Foo) || Foo; return Foo; })(); var Bar2 = (function () { - var Bar = function Bar() { - babelHelpers.classCallCheck(this, Bar); - }; + function Bar() { + babelHelpers.classCallCheck(this, _Bar2); + } + var _Bar2 = Bar; Bar = foo(Bar) || Bar; Bar = bar(Bar) || Bar; return Bar; })(); var Baz = (function () { - var Baz = function Baz(baz) { - babelHelpers.classCallCheck(this, Baz); + function Baz(baz) { + babelHelpers.classCallCheck(this, _Baz); this.baz = baz; - }; + } + var _Baz = Baz; Baz = foo(Baz) || Baz; return Baz; })();