fix decorator interop - fixes #1277

This commit is contained in:
Sebastian McKenzie
2015-04-25 18:18:30 +01:00
parent 00c0a958db
commit deed48a3db
22 changed files with 124 additions and 81 deletions

View File

@@ -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",

View File

@@ -1 +0,0 @@
this.KEY = INITIALIZERS.KEY.call(this);

View File

@@ -1 +0,0 @@
CONSTRUCTOR.KEY = INITIALIZERS.KEY.call(CONSTRUCTOR);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
})

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
})();
})();

View File

@@ -12,10 +12,5 @@ var Foo = (function (_Bar) {
}
babelHelpers.inherits(Foo, _Bar);
babelHelpers.createClass(Foo, [{
key: "bar",
value: undefined,
enumerable: true
}]);
return Foo;
})(Bar);
})(Bar);

View File

@@ -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;
})();
var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
this.bar = undefined;
};

View File

@@ -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;
})();
var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
this.bar = "foo";
};

View File

@@ -10,10 +10,5 @@ var Foo = (function (_Bar) {
}
babelHelpers.inherits(Foo, _Bar);
babelHelpers.createClass(Foo, [{
key: "bar",
value: undefined,
enumerable: true
}]);
return Foo;
})(Bar);

View File

@@ -9,10 +9,5 @@ var Foo = (function (_Bar) {
}
babelHelpers.inherits(Foo, _Bar);
babelHelpers.createClass(Foo, [{
key: "bar",
value: undefined,
enumerable: true
}]);
return Foo;
})(Bar);

View File

@@ -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");

View File

@@ -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;
})();
})();

View File

@@ -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");

View File

@@ -15,6 +15,6 @@ var Foo = (function () {
},
enumerable: true
}], null, _staticInitializers);
Foo.foo = _staticInitializers.foo.call(Foo);
babelHelpers.defineDecoratedPropertyDescriptor(Foo, "foo", _staticInitializers);
return Foo;
})();
})();

View File

@@ -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;
})();
})();

View File

@@ -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;
})();

View File

@@ -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");

View File

@@ -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";
}
}]);