diff --git a/packages/babel-helper-replace-supers/src/index.js b/packages/babel-helper-replace-supers/src/index.js index dff7328e68..139df00e4b 100644 --- a/packages/babel-helper-replace-supers/src/index.js +++ b/packages/babel-helper-replace-supers/src/index.js @@ -52,6 +52,10 @@ const visitor = { if (!path.isArrowFunctionExpression()) path.skip(); }, + ClassProperty(path) { + if (!path.node.static) path.skip(); + }, + ReturnStatement(path, state) { if (!path.getFunctionParent().isArrowFunctionExpression()) { state.returns.push(path); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/actual.js new file mode 100644 index 0000000000..2658970d52 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/actual.js @@ -0,0 +1,3 @@ +class Foo { + static fn = () => console.log(this); +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/expected.js new file mode 100644 index 0000000000..7dc20a774c --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/expected.js @@ -0,0 +1,7 @@ +var _this = this; + +class Foo { + static fn = function () { + return console.log(_this); + }; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/options.json new file mode 100644 index 0000000000..5a9ea4593f --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-static-this-without-transform/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", "transform-es2015-arrow-functions", "syntax-class-properties"] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/actual.js new file mode 100644 index 0000000000..963f1aa2a6 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/actual.js @@ -0,0 +1,3 @@ +class Foo { + fn = () => console.log(this); +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/options.json new file mode 100644 index 0000000000..4f5f271f1a --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/general/arrow-this-without-transform/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["external-helpers", "transform-es2015-arrow-functions", "syntax-class-properties"], + "throws": "Unable to transform arrow inside class property" +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/actual.js new file mode 100644 index 0000000000..d1a3e41179 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/actual.js @@ -0,0 +1,28 @@ +() => { + class Foo { + fn = () => console.log(this); + static fn = () => console.log(this); + } +}; + +() => class Bar { + fn = () => console.log(this); + static fn = () => console.log(this); +}; + +() => { + class Baz { + fn = () => console.log(this); + force = force + static fn = () => console.log(this); + + constructor(force) {} + } +}; + +var qux = function() { + class Qux { + fn = () => console.log(this); + static fn = () => console.log(this); + } +}.bind(this) diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/expected.js new file mode 100644 index 0000000000..12a888802d --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/expected.js @@ -0,0 +1,121 @@ +var _this = this; + +(function () { + class Foo { + constructor() { + var _this2 = this; + + Object.defineProperty(this, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this2); + } + }); + } + + } + + Object.defineProperty(Foo, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this); + } + }); +}); + +(function () { + var _class, _temp; + + return _temp = _class = class Bar { + constructor() { + var _this3 = this; + + Object.defineProperty(this, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this3); + } + }); + } + + }, Object.defineProperty(_class, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this); + } + }), _temp; +}); + +(function () { + class Baz { + constructor(force) { + _initialiseProps.call(this); + } + + } + + Object.defineProperty(Baz, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this); + } + }); + + var _initialiseProps = function () { + var _this4 = this; + + Object.defineProperty(this, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this4); + } + }); + Object.defineProperty(this, "force", { + configurable: true, + enumerable: true, + writable: true, + value: force + }); + }; +}); + +var qux = function () { + var _this6 = this; + + class Qux { + constructor() { + var _this5 = this; + + Object.defineProperty(this, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this5); + } + }); + } + + } + + Object.defineProperty(Qux, "fn", { + configurable: true, + enumerable: true, + writable: true, + value: function () { + return console.log(_this6); + } + }); +}.bind(this); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/options.json new file mode 100644 index 0000000000..4207909c7f --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6153/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", "transform-class-properties", "transform-es2015-arrow-functions"] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/actual.js new file mode 100644 index 0000000000..a08817f6a4 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/actual.js @@ -0,0 +1,8 @@ +class Test { + constructor() { + class Other extends Test { + a = () => super.test; + static a = () => super.test; + } + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/expected.js new file mode 100644 index 0000000000..5604d2ff3c --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/expected.js @@ -0,0 +1,53 @@ +"use strict"; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Test = function Test() { + var _this2 = this; + + _classCallCheck(this, Test); + + var Other = function (_Test) { + _inherits(Other, _Test); + + function Other() { + var _ref; + + var _temp, _this; + + _classCallCheck(this, Other); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _possibleConstructorReturn(_this, (_temp = _this = _possibleConstructorReturn(this, (_ref = Other.__proto__ || Object.getPrototypeOf(Other)).call.apply(_ref, [this].concat(args))), Object.defineProperty(_this, "a", { + configurable: true, + enumerable: true, + writable: true, + value: function value() { + return _get(Other.prototype.__proto__ || Object.getPrototypeOf(Other.prototype), "test", _this); + } + }), _temp)); + } + + return Other; + }(Test); + + Object.defineProperty(Other, "a", { + configurable: true, + enumerable: true, + writable: true, + value: function value() { + return _get(Test.prototype.__proto__ || Object.getPrototypeOf(Test.prototype), "test", _this2); + } + }); +}; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/options.json new file mode 100644 index 0000000000..05581748b9 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/6154/options.json @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-2"] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/T2983/options.json similarity index 100% rename from packages/babel-plugin-transform-class-properties/test/fixtures/regression/options.json rename to packages/babel-plugin-transform-class-properties/test/fixtures/regression/T2983/options.json diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/regression/T6719/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/T6719/options.json new file mode 100644 index 0000000000..79fb997f2d --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/regression/T6719/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", ["transform-class-properties", {"loose": true}], "transform-es2015-classes", "transform-es2015-block-scoping", "syntax-class-properties"] +} diff --git a/packages/babel-traverse/src/path/conversion.js b/packages/babel-traverse/src/path/conversion.js index 3ae7de7267..d145e3e840 100644 --- a/packages/babel-traverse/src/path/conversion.js +++ b/packages/babel-traverse/src/path/conversion.js @@ -123,7 +123,7 @@ function hoistFunctionEnvironment( p => (p.isFunction() && !p.isArrowFunctionExpression()) || p.isProgram() || - p.isClassProperty(), + p.isClassProperty({ static: false }), ); const inConstructor = thisEnvFn && thisEnvFn.node.kind === "constructor"; @@ -148,28 +148,22 @@ function hoistFunctionEnvironment( "Unable to handle nested super() usage in arrow", ); } - const allSuperCalls = []; thisEnvFn.traverse({ - Function: child => { - if ( - child.isArrowFunctionExpression() || - child.isClassProperty() || - child === fnPath - ) { - return; - } + Function(child) { + if (child.isArrowFunctionExpression()) return; + child.skip(); + }, + ClassProperty(child) { + if (child.node.static) return; child.skip(); }, CallExpression(child) { if (!child.get("callee").isSuper()) return; - allSuperCalls.push(child); }, }); - const superBinding = getSuperBinding(thisEnvFn); - allSuperCalls.forEach(superCall => superCall.get("callee").replaceWith(t.identifier(superBinding)), ); @@ -399,15 +393,12 @@ function getThisBinding(thisEnvFn, inConstructor) { const supers = new WeakSet(); thisEnvFn.traverse({ - Function: child => { - if ( - child.isArrowFunctionExpression() || - child.isClassProperty() || - child === this - ) { - return; - } - + Function(child) { + if (child.isArrowFunctionExpression()) return; + child.skip(); + }, + ClassProperty(child) { + if (child.node.static) return; child.skip(); }, CallExpression(child) { @@ -529,8 +520,12 @@ function getScopeInformation(fnPath) { const superCalls = []; fnPath.traverse({ + ClassProperty(child) { + if (child.node.static) return; + child.skip(); + }, Function(child) { - if (child.isArrowFunctionExpression() || child.isClassProperty()) return; + if (child.isArrowFunctionExpression()) return; child.skip(); }, ThisExpression(child) {