diff --git a/src/babel/transformation/helpers/memoise-decorators.js b/src/babel/transformation/helpers/memoise-decorators.js new file mode 100644 index 0000000000..9e012bdf72 --- /dev/null +++ b/src/babel/transformation/helpers/memoise-decorators.js @@ -0,0 +1,33 @@ +import * as t from "../../types"; + +export default function (decorators, scope) { + for (var i = 0; i < decorators.length; i++) { + var decorator = decorators[i]; + var expression = decorator.expression; + if (!t.isMemberExpression(expression)) continue; + + var temp = scope.generateMemoisedReference(expression.object); + var ref; + + var nodes = []; + + if (temp) { + ref = temp; + nodes.push(t.assignmentExpression("=", temp, expression.object)); + } else { + ref = expression.object; + } + + nodes.push(t.callExpression( + t.memberExpression( + t.memberExpression(ref, expression.property, expression.computed), + t.identifier("bind") + ), + [ref] + )); + + decorator.expression = t.sequenceExpression(nodes); + } + + return decorators; +} diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index 981a6cf6d3..88f2f160b8 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -1,3 +1,4 @@ +import memoiseDecorators from "../../helpers/memoise-decorators"; import ReplaceSupers from "../../helpers/replace-supers"; import * as nameMethod from "../../helpers/name-method"; import * as defineMap from "../../helpers/define-map"; @@ -292,6 +293,10 @@ class ClassTransformer { var node = classBody[i]; var path = classBodyPaths[i]; + if (node.decorators) { + memoiseDecorators(node.decorators, this.scope); + } + if (t.isMethodDefinition(node)) { var isConstructor = node.kind === "constructor"; if (isConstructor) this.verifyConstructor(path); diff --git a/src/babel/transformation/transformers/es7/decorators.js b/src/babel/transformation/transformers/es7/decorators.js index a7980b6920..d6f69bbf5b 100644 --- a/src/babel/transformation/transformers/es7/decorators.js +++ b/src/babel/transformation/transformers/es7/decorators.js @@ -1,3 +1,4 @@ +import memoiseDecorators from "../../helpers/memoise-decorators"; import * as defineMap from "../../helpers/define-map"; import * as t from "../../../types"; @@ -24,7 +25,9 @@ export function ObjectExpression(node, parent, scope, file) { var mutatorMap = {}; for (var i = 0; i < node.properties.length; i++) { - defineMap.push(mutatorMap, node.properties[i], null, file); + var prop = node.properties[i]; + if (prop.decorators) memoiseDecorators(prop.decorators, scope); + defineMap.push(mutatorMap, prop, null, file); } var obj = defineMap.toClassObject(mutatorMap); diff --git a/test/core/fixtures/transformation/es7.decorators/member-expressions/exec.js b/test/core/fixtures/transformation/es7.decorators/member-expressions/exec.js new file mode 100644 index 0000000000..81bc4716a4 --- /dev/null +++ b/test/core/fixtures/transformation/es7.decorators/member-expressions/exec.js @@ -0,0 +1,18 @@ +var foo = { + bar: function () { assert.equal(this, foo); }, + foobar: { + bar: function () { assert.equal(this, foo.foobar); }, + } +}; + +(class { + @foo.bar + @foo.foobar.bar + bar() {} +}); + +({ + @foo.bar + @foo.foobar.bar + bar() {} +});