diff --git a/src/babel/transformation/file/index.js b/src/babel/transformation/file/index.js index c83194fdfe..0b1b86ab63 100644 --- a/src/babel/transformation/file/index.js +++ b/src/babel/transformation/file/index.js @@ -60,6 +60,7 @@ export default class File { "create-class", "create-decorated-class", "create-decorated-object", + "define-decorated-property-descriptor", "tagged-template-literal", "tagged-template-literal-loose", "to-array", diff --git a/src/babel/transformation/templates/call-instance-decorator.js b/src/babel/transformation/templates/call-instance-decorator.js deleted file mode 100644 index 0fcedc4e7d..0000000000 --- a/src/babel/transformation/templates/call-instance-decorator.js +++ /dev/null @@ -1 +0,0 @@ -this.KEY = INITIALIZERS.KEY.call(this); diff --git a/src/babel/transformation/templates/call-static-decorator.js b/src/babel/transformation/templates/call-static-decorator.js deleted file mode 100644 index cca17bbf3b..0000000000 --- a/src/babel/transformation/templates/call-static-decorator.js +++ /dev/null @@ -1 +0,0 @@ -CONSTRUCTOR.KEY = INITIALIZERS.KEY.call(CONSTRUCTOR); diff --git a/src/babel/transformation/templates/helper-create-decorated-class.js b/src/babel/transformation/templates/helper-create-decorated-class.js index 8c36074cdb..db321a5ef8 100644 --- a/src/babel/transformation/templates/helper-create-decorated-class.js +++ b/src/babel/transformation/templates/helper-create-decorated-class.js @@ -23,7 +23,11 @@ throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator); } } - if (initializers) initializers[key] = descriptor.initializer; + + if (descriptor.initializer) { + initializers[key] = descriptor; + continue; + } } Object.defineProperty(target, key, descriptor); diff --git a/src/babel/transformation/templates/helper-create-decorated-object.js b/src/babel/transformation/templates/helper-create-decorated-object.js index 03e2e81b52..6af1fbf27e 100644 --- a/src/babel/transformation/templates/helper-create-decorated-object.js +++ b/src/babel/transformation/templates/helper-create-decorated-object.js @@ -13,7 +13,7 @@ descriptor.enumerable = true; descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; + descriptor.writable = true; if (decorators) { for (var f = 0; f < decorators.length; f++) { @@ -26,6 +26,8 @@ } } + descriptor.value = descriptor.initializer(); + Object.defineProperty(target, key, descriptor); } diff --git a/src/babel/transformation/templates/helper-define-decorated-property-descriptor.js b/src/babel/transformation/templates/helper-define-decorated-property-descriptor.js new file mode 100644 index 0000000000..3b9c9e729e --- /dev/null +++ b/src/babel/transformation/templates/helper-define-decorated-property-descriptor.js @@ -0,0 +1,12 @@ +(function (target, key, descriptors) { + var _descriptor = descriptors[key]; + + // clone it + var descriptor = {}; + for (var _key in _descriptor) descriptor[_key] = _descriptor[_key]; + + // initialize it + descriptor.value = descriptor.initializer(); + + Object.defineProperty(target, key, descriptor); +}) diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index bf3fe9b413..a17a2becff 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -554,35 +554,39 @@ class ClassTransformer { node.value = t.functionExpression(null, [], t.blockStatement(body)); this.pushToMap(node, true, "initializer"); + var initializers; + var body; + var target; if (node.static) { - this.staticPropBody.push(util.template("call-static-decorator", { - INITIALIZERS: this.staticInitializersId ||= this.scope.generateUidIdentifier("staticInitializers"), - CONSTRUCTOR: this.classRef, - KEY: node.key, - }, true)); + initializers = this.staticInitializersId ||= this.scope.generateUidIdentifier("staticInitializers"); + body = this.staticPropBody; + target = this.classRef; } else { - this.instancePropBody.push(util.template("call-instance-decorator", { - INITIALIZERS: this.instanceInitializersId ||= this.scope.generateUidIdentifier("instanceInitializers"), - KEY: node.key - }, true)); + initializers = this.instanceInitializersId ||= this.scope.generateUidIdentifier("instanceInitializers"); + body = this.instancePropBody; + target = t.thisExpression(); } + + body.push(t.expressionStatement( + t.callExpression(this.file.addHelper("define-decorated-property-descriptor"), [ + target, + t.literal(node.key.name), + initializers + ]) + )); } else { - if (!node.static && node.value) { + node.value ||= t.identifier("undefined"); + + if (node.static) { + // can just be added to the static map + this.pushToMap(node, true); + } else if (node.value) { // add this to the instancePropBody which will be added after the super call in a derived constructor // or at the start of a constructor for a non-derived constructor this.instancePropBody.push(t.expressionStatement( t.assignmentExpression("=", t.memberExpression(t.thisExpression(), node.key), node.value) )); - - node.value = null; } - - if (!node.value) { - node.value = t.identifier("undefined"); - } - - // can just be added to the static map - this.pushToMap(node, true); } } diff --git a/src/babel/transformation/transformers/es7/decorators.js b/src/babel/transformation/transformers/es7/decorators.js index d6f69bbf5b..2fc10f5eed 100644 --- a/src/babel/transformation/transformers/es7/decorators.js +++ b/src/babel/transformation/transformers/es7/decorators.js @@ -27,7 +27,16 @@ export function ObjectExpression(node, parent, scope, file) { for (var i = 0; i < node.properties.length; i++) { var prop = node.properties[i]; if (prop.decorators) memoiseDecorators(prop.decorators, scope); - defineMap.push(mutatorMap, prop, null, file); + + + if (prop.kind === "init") { + prop.kind = ""; + prop.value = t.functionExpression(null, [], t.blockStatement([ + t.returnStatement(prop.value) + ])); + } + + defineMap.push(mutatorMap, prop, "initializer", file); } var obj = defineMap.toClassObject(mutatorMap); diff --git a/test/core/fixtures/transformation/es7.class-properties/constructor-collision/expected.js b/test/core/fixtures/transformation/es7.class-properties/constructor-collision/expected.js index 8122a0d904..7717ef7e3d 100644 --- a/test/core/fixtures/transformation/es7.class-properties/constructor-collision/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/constructor-collision/expected.js @@ -12,14 +12,10 @@ var Foo = (function () { } babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }, { key: "__initializeProperties", value: function __initializeProperties() { this.bar = foo; } }]); return Foo; -})(); \ No newline at end of file +})(); diff --git a/test/core/fixtures/transformation/es7.class-properties/derived/expected.js b/test/core/fixtures/transformation/es7.class-properties/derived/expected.js index 3f8f712ec7..1e6b388886 100644 --- a/test/core/fixtures/transformation/es7.class-properties/derived/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/derived/expected.js @@ -12,10 +12,5 @@ var Foo = (function (_Bar) { } babelHelpers.inherits(Foo, _Bar); - babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }]); return Foo; -})(Bar); \ No newline at end of file +})(Bar); diff --git a/test/core/fixtures/transformation/es7.class-properties/instance-undefined/expected.js b/test/core/fixtures/transformation/es7.class-properties/instance-undefined/expected.js index 4fed431790..cc057f33bb 100644 --- a/test/core/fixtures/transformation/es7.class-properties/instance-undefined/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/instance-undefined/expected.js @@ -1,14 +1,6 @@ "use strict"; -var Foo = (function () { - function Foo() { - babelHelpers.classCallCheck(this, Foo); - } - - babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }]); - return Foo; -})(); \ No newline at end of file +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); + this.bar = undefined; +}; \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.class-properties/instance/expected.js b/test/core/fixtures/transformation/es7.class-properties/instance/expected.js index 69e1324fea..8f200f662d 100644 --- a/test/core/fixtures/transformation/es7.class-properties/instance/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/instance/expected.js @@ -1,15 +1,6 @@ "use strict"; -var Foo = (function () { - function Foo() { - babelHelpers.classCallCheck(this, Foo); - this.bar = "foo"; - } - - babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }]); - return Foo; -})(); \ No newline at end of file +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); + this.bar = "foo"; +}; diff --git a/test/core/fixtures/transformation/es7.class-properties/super-expression/expected.js b/test/core/fixtures/transformation/es7.class-properties/super-expression/expected.js index fe3a1cdc34..0dc028074d 100644 --- a/test/core/fixtures/transformation/es7.class-properties/super-expression/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/super-expression/expected.js @@ -10,10 +10,5 @@ var Foo = (function (_Bar) { } babelHelpers.inherits(Foo, _Bar); - babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }]); return Foo; })(Bar); \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.class-properties/super-statement/expected.js b/test/core/fixtures/transformation/es7.class-properties/super-statement/expected.js index 6d64624dcd..17c7c8dfb8 100644 --- a/test/core/fixtures/transformation/es7.class-properties/super-statement/expected.js +++ b/test/core/fixtures/transformation/es7.class-properties/super-statement/expected.js @@ -9,10 +9,5 @@ var Foo = (function (_Bar) { } babelHelpers.inherits(Foo, _Bar); - babelHelpers.createClass(Foo, [{ - key: "bar", - value: undefined, - enumerable: true - }]); return Foo; })(Bar); \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/exec.js b/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/exec.js new file mode 100644 index 0000000000..03b00b8175 --- /dev/null +++ b/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/exec.js @@ -0,0 +1,14 @@ +function noop() {} + +class Foo { + @noop + bar = "foobar"; + + @noop + foo() { + return "bar"; + } +} + +assert.equal(new Foo().bar, "foobar"); +assert.equal(new Foo().foo(), "bar"); diff --git a/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/expected.js b/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/expected.js index a87c3fc846..6753403675 100644 --- a/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class-init-instance-props/expected.js @@ -5,7 +5,7 @@ var Foo = (function () { function Foo() { babelHelpers.classCallCheck(this, Foo); - this.foo = _instanceInitializers.foo.call(this); + babelHelpers.defineDecoratedPropertyDescriptor(this, "foo", _instanceInitializers); } babelHelpers.createDecoratedClass(Foo, [{ @@ -17,4 +17,4 @@ var Foo = (function () { enumerable: true }], null, _instanceInitializers); return Foo; -})(); +})(); \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.decorators/class-init-static-props/exec.js b/test/core/fixtures/transformation/es7.decorators/class-init-static-props/exec.js new file mode 100644 index 0000000000..a343d78640 --- /dev/null +++ b/test/core/fixtures/transformation/es7.decorators/class-init-static-props/exec.js @@ -0,0 +1,14 @@ +function noop() {} + +class Foo { + @noop + static bar = "foobar"; + + @noop + static foo() { + return "bar"; + } +} + +assert.equal(Foo.bar, "foobar"); +assert.equal(Foo.foo(), "bar"); diff --git a/test/core/fixtures/transformation/es7.decorators/class-init-static-props/expected.js b/test/core/fixtures/transformation/es7.decorators/class-init-static-props/expected.js index f7978b1856..c365832ed7 100644 --- a/test/core/fixtures/transformation/es7.decorators/class-init-static-props/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class-init-static-props/expected.js @@ -15,6 +15,6 @@ var Foo = (function () { }, enumerable: true }], null, _staticInitializers); - Foo.foo = _staticInitializers.foo.call(Foo); + babelHelpers.defineDecoratedPropertyDescriptor(Foo, "foo", _staticInitializers); return Foo; -})(); +})(); \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.decorators/class-no-init-instance-props/expected.js b/test/core/fixtures/transformation/es7.decorators/class-no-init-instance-props/expected.js index 02b348ffff..b0975298af 100644 --- a/test/core/fixtures/transformation/es7.decorators/class-no-init-instance-props/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class-no-init-instance-props/expected.js @@ -5,7 +5,7 @@ var Foo = (function () { function Foo() { babelHelpers.classCallCheck(this, Foo); - this.foo = _instanceInitializers.foo.call(this); + babelHelpers.defineDecoratedPropertyDescriptor(this, "foo", _instanceInitializers); } babelHelpers.createDecoratedClass(Foo, [{ @@ -15,4 +15,4 @@ var Foo = (function () { enumerable: true }], null, _instanceInitializers); return Foo; -})(); +})(); \ No newline at end of file diff --git a/test/core/fixtures/transformation/es7.decorators/class-no-init-static-props/expected.js b/test/core/fixtures/transformation/es7.decorators/class-no-init-static-props/expected.js index aca6f49378..89d557f801 100644 --- a/test/core/fixtures/transformation/es7.decorators/class-no-init-static-props/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/class-no-init-static-props/expected.js @@ -13,6 +13,6 @@ var Foo = (function () { initializer: function () {}, enumerable: true }], null, _staticInitializers); - Foo.foo = _staticInitializers.foo.call(Foo); + babelHelpers.defineDecoratedPropertyDescriptor(Foo, "foo", _staticInitializers); return Foo; })(); diff --git a/test/core/fixtures/transformation/es7.decorators/object/exec.js b/test/core/fixtures/transformation/es7.decorators/object/exec.js new file mode 100644 index 0000000000..6868020f23 --- /dev/null +++ b/test/core/fixtures/transformation/es7.decorators/object/exec.js @@ -0,0 +1,15 @@ +function override(target, key, descriptor) { + descriptor.initializer = function () { + return "lol"; + }; +} + +var obj = { + @override + foo: "bar", + + bar: "heh" +}; + +assert.equal(obj.foo, "lol"); +assert.equal(obj.bar, "heh"); diff --git a/test/core/fixtures/transformation/es7.decorators/object/expected.js b/test/core/fixtures/transformation/es7.decorators/object/expected.js index 9cb660df56..b6259d0cdc 100644 --- a/test/core/fixtures/transformation/es7.decorators/object/expected.js +++ b/test/core/fixtures/transformation/es7.decorators/object/expected.js @@ -3,12 +3,18 @@ var obj = babelHelpers.createDecoratedObject([{ key: "bar", decorators: [foo], - value: function value() {} + initializer: function initializer() { + return function () {}; + } }, { key: "foo", decorators: [bar], - value: "lol" + initializer: function initializer() { + return "lol"; + } }, { key: "yes", - value: "wow" -}]); + initializer: function initializer() { + return "wow"; + } +}]); \ No newline at end of file