diff --git a/src/babel/transformation/transformers/es6/classes/vanilla.js b/src/babel/transformation/transformers/es6/classes/vanilla.js index c358dfeba9..421e9f948b 100644 --- a/src/babel/transformation/transformers/es6/classes/vanilla.js +++ b/src/babel/transformation/transformers/es6/classes/vanilla.js @@ -52,7 +52,20 @@ var verifyConstructorVisitor = { ThisExpression(node, parent, scope, state) { if (state.isDerived && !state.hasBareSuper) { - throw this.errorWithNode("'this' is not allowed before super()"); + if (this.inShadow()) { + var thisAlias = state.constructorPath.getData("this"); + + if (!thisAlias) { + thisAlias = state.constructorPath.setData( + "this", + state.constructorPath.scope.generateUidIdentifier("this") + ); + } + + return thisAlias; + } else { + throw this.errorWithNode("'this' is not allowed before super()"); + } } }, @@ -429,13 +442,21 @@ export default class ClassTransformer { verifyConstructor(path: NodePath) { var state = { - hasBareSuper: false, - bareSuper: null, - isDerived: this.isDerived, - file: this.file + constructorPath: path.get("value"), + hasBareSuper: false, + bareSuper: null, + isDerived: this.isDerived, + file: this.file, }; - path.get("value").traverse(verifyConstructorVisitor, state); + state.constructorPath.traverse(verifyConstructorVisitor, state); + + var thisAlias = state.constructorPath.getData("this"); + if (thisAlias && state.bareSuper) { + state.bareSuper.insertAfter(t.variableDeclaration("var", [ + t.variableDeclarator(thisAlias, t.thisExpression()) + ])); + } this.bareSuper = state.bareSuper; diff --git a/src/babel/transformation/transformers/internal/shadow-functions.js b/src/babel/transformation/transformers/internal/shadow-functions.js index 308a63a386..0f401af035 100644 --- a/src/babel/transformation/transformers/internal/shadow-functions.js +++ b/src/babel/transformation/transformers/internal/shadow-functions.js @@ -6,7 +6,8 @@ export var metadata = { function remap(path, key, create) { // ensure that we're shadowed - if (!path.inShadow()) return; + var shadowPath = path.inShadow(); + if (!shadowPath || shadowPath.isArrowFunctionExpression()) return; var shadowFunction = path.node._shadowedFunctionLiteral; var currentFunction; diff --git a/src/babel/traversal/path/ancestry.js b/src/babel/traversal/path/ancestry.js index cdfdfde44e..2e7100b678 100644 --- a/src/babel/traversal/path/ancestry.js +++ b/src/babel/traversal/path/ancestry.js @@ -178,7 +178,7 @@ export function inShadow() { var path = this; while (path) { if (path.isFunction()) { - if (path.node.shadow) { + if (path.node.shadow || path.isArrowFunctionExpression()) { return path; } else { return null; diff --git a/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/actual.js b/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/actual.js new file mode 100644 index 0000000000..8d322b3093 --- /dev/null +++ b/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/actual.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + constructor() { + super(() => { + this.test; + }); + } +} diff --git a/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/expected.js b/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/expected.js new file mode 100644 index 0000000000..4140da0602 --- /dev/null +++ b/test/core/fixtures/transformation/es6.classes/delay-arrow-function-for-bare-super-derived/expected.js @@ -0,0 +1,16 @@ +"use strict"; + +var Foo = (function (_Bar) { + function Foo() { + babelHelpers.classCallCheck(this, Foo); + + babelHelpers.get(Object.getPrototypeOf(Foo.prototype), "constructor", this).call(this, function () { + _this.test; + }); + + var _this = this; + } + + babelHelpers.inherits(Foo, _Bar); + return Foo; +})(Bar);