Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 33 additions & 19 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1277,15 +1277,15 @@ namespace ts {
* @param node The declaration node.
* @param allDecorators An object containing all of the decorators for the declaration.
*/
function transformAllDecoratorsOfDeclaration(node: Declaration, allDecorators: AllDecorators) {
function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators) {
if (!allDecorators) {
return undefined;
}

const decoratorExpressions: Expression[] = [];
addRange(decoratorExpressions, map(allDecorators.decorators, transformDecorator));
addRange(decoratorExpressions, flatMap(allDecorators.parameters, transformDecoratorsOfParameter));
addTypeMetadata(node, decoratorExpressions);
addTypeMetadata(node, container, decoratorExpressions);
return decoratorExpressions;
}

Expand Down Expand Up @@ -1334,7 +1334,7 @@ namespace ts {
*/
function generateClassElementDecorationExpression(node: ClassExpression | ClassDeclaration, member: ClassElement) {
const allDecorators = getAllDecoratorsOfClassElement(node, member);
const decoratorExpressions = transformAllDecoratorsOfDeclaration(member, allDecorators);
const decoratorExpressions = transformAllDecoratorsOfDeclaration(member, node, allDecorators);
if (!decoratorExpressions) {
return undefined;
}
Expand Down Expand Up @@ -1415,7 +1415,7 @@ namespace ts {
*/
function generateConstructorDecorationExpression(node: ClassExpression | ClassDeclaration) {
const allDecorators = getAllDecoratorsOfConstructor(node);
const decoratorExpressions = transformAllDecoratorsOfDeclaration(node, allDecorators);
const decoratorExpressions = transformAllDecoratorsOfDeclaration(node, node, allDecorators);
if (!decoratorExpressions) {
return undefined;
}
Expand Down Expand Up @@ -1468,37 +1468,37 @@ namespace ts {
* @param node The declaration node.
* @param decoratorExpressions The destination array to which to add new decorator expressions.
*/
function addTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
function addTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
if (USE_NEW_TYPE_METADATA_FORMAT) {
addNewTypeMetadata(node, decoratorExpressions);
addNewTypeMetadata(node, container, decoratorExpressions);
}
else {
addOldTypeMetadata(node, decoratorExpressions);
addOldTypeMetadata(node, container, decoratorExpressions);
}
}

function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
function addOldTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
if (compilerOptions.emitDecoratorMetadata) {
if (shouldAddTypeMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(context, "design:type", serializeTypeOfNode(node)));
}
if (shouldAddParamTypesMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node)));
decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node, container)));
}
if (shouldAddReturnTypeMetadata(node)) {
decoratorExpressions.push(createMetadataHelper(context, "design:returntype", serializeReturnTypeOfNode(node)));
}
}
}

function addNewTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
function addNewTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
if (compilerOptions.emitDecoratorMetadata) {
let properties: ObjectLiteralElementLike[];
if (shouldAddTypeMetadata(node)) {
(properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node))));
}
if (shouldAddParamTypesMetadata(node)) {
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node))));
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node, container))));
}
if (shouldAddReturnTypeMetadata(node)) {
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
Expand Down Expand Up @@ -1543,12 +1543,16 @@ namespace ts {
* @param node The node to test.
*/
function shouldAddParamTypesMetadata(node: Declaration): boolean {
const kind = node.kind;
return kind === SyntaxKind.ClassDeclaration
|| kind === SyntaxKind.ClassExpression
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor;
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
return getFirstConstructorWithBody(<ClassLikeDeclaration>node) !== undefined;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return true;
}
return false;
}

/**
Expand Down Expand Up @@ -1596,7 +1600,7 @@ namespace ts {
*
* @param node The node that should have its parameter types serialized.
*/
function serializeParameterTypesOfNode(node: Node): Expression {
function serializeParameterTypesOfNode(node: Node, container: ClassLikeDeclaration): Expression {
const valueDeclaration =
isClassLike(node)
? getFirstConstructorWithBody(node)
Expand All @@ -1606,7 +1610,7 @@ namespace ts {

const expressions: Expression[] = [];
if (valueDeclaration) {
const parameters = valueDeclaration.parameters;
const parameters = getParametersOfDecoratedDeclaration(valueDeclaration, container);
const numParameters = parameters.length;
for (let i = 0; i < numParameters; i++) {
const parameter = parameters[i];
Expand All @@ -1625,6 +1629,16 @@ namespace ts {
return createArrayLiteral(expressions);
}

function getParametersOfDecoratedDeclaration(node: FunctionLikeDeclaration, container: ClassLikeDeclaration) {
if (container && node.kind === SyntaxKind.GetAccessor) {
const { setAccessor } = getAllAccessorDeclarations(container.members, <AccessorDeclaration>node);
if (setAccessor) {
return setAccessor.parameters;
}
}
return node.parameters;
}

/**
* Serializes the return type of a node for use with decorator type metadata.
*
Expand Down
6 changes: 1 addition & 5 deletions tests/baselines/reference/decoratedClassExportsCommonJS1.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
let Testing123 = Testing123_1 = class Testing123 {
};
Testing123.prop1 = Testing123_1.prop0;
Testing123 = Testing123_1 = __decorate([
Something({ v: () => Testing123_1 }),
__metadata("design:paramtypes", [])
Something({ v: () => Testing123_1 })
], Testing123);
exports.Testing123 = Testing123;
var Testing123_1;
6 changes: 1 addition & 5 deletions tests/baselines/reference/decoratedClassExportsCommonJS2.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
let Testing123 = Testing123_1 = class Testing123 {
};
Testing123 = Testing123_1 = __decorate([
Something({ v: () => Testing123_1 }),
__metadata("design:paramtypes", [])
Something({ v: () => Testing123_1 })
], Testing123);
exports.Testing123 = Testing123;
var Testing123_1;
6 changes: 1 addition & 5 deletions tests/baselines/reference/decoratedClassExportsSystem1.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ System.register([], function (exports_1, context_1) {
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __moduleName = context_1 && context_1.id;
var Testing123, Testing123_1;
return {
Expand All @@ -29,8 +26,7 @@ System.register([], function (exports_1, context_1) {
};
Testing123.prop1 = Testing123_1.prop0;
Testing123 = Testing123_1 = __decorate([
Something({ v: () => Testing123_1 }),
__metadata("design:paramtypes", [])
Something({ v: () => Testing123_1 })
], Testing123);
exports_1("Testing123", Testing123);
}
Expand Down
6 changes: 1 addition & 5 deletions tests/baselines/reference/decoratedClassExportsSystem2.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ System.register([], function (exports_1, context_1) {
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __moduleName = context_1 && context_1.id;
var Testing123, Testing123_1;
return {
Expand All @@ -25,8 +22,7 @@ System.register([], function (exports_1, context_1) {
Testing123 = Testing123_1 = class Testing123 {
};
Testing123 = Testing123_1 = __decorate([
Something({ v: () => Testing123_1 }),
__metadata("design:paramtypes", [])
Something({ v: () => Testing123_1 })
], Testing123);
exports_1("Testing123", Testing123);
}
Expand Down
135 changes: 135 additions & 0 deletions tests/baselines/reference/decoratorOnClassAccessor8.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//// [decoratorOnClassAccessor8.ts]
declare function dec<T>(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T>;

class A {
@dec get x() { return 0; }
set x(value: number) { }
}

class B {
get x() { return 0; }
@dec set x(value: number) { }
}

class C {
@dec set x(value: number) { }
get x() { return 0; }
}

class D {
set x(value: number) { }
@dec get x() { return 0; }
}

class E {
@dec get x() { return 0; }
}

class F {
@dec set x(value: number) { }
}

//// [decoratorOnClassAccessor8.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var A = (function () {
function A() {
}
Object.defineProperty(A.prototype, "x", {
get: function () { return 0; },
set: function (value) { },
enumerable: true,
configurable: true
});
return A;
}());
__decorate([
dec,
__metadata("design:type", Object),
__metadata("design:paramtypes", [Number])
], A.prototype, "x", null);
var B = (function () {
function B() {
}
Object.defineProperty(B.prototype, "x", {
get: function () { return 0; },
set: function (value) { },
enumerable: true,
configurable: true
});
return B;
}());
__decorate([
dec,
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], B.prototype, "x", null);
var C = (function () {
function C() {
}
Object.defineProperty(C.prototype, "x", {
get: function () { return 0; },
set: function (value) { },
enumerable: true,
configurable: true
});
return C;
}());
__decorate([
dec,
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], C.prototype, "x", null);
var D = (function () {
function D() {
}
Object.defineProperty(D.prototype, "x", {
get: function () { return 0; },
set: function (value) { },
enumerable: true,
configurable: true
});
return D;
}());
__decorate([
dec,
__metadata("design:type", Object),
__metadata("design:paramtypes", [Number])
], D.prototype, "x", null);
var E = (function () {
function E() {
}
Object.defineProperty(E.prototype, "x", {
get: function () { return 0; },
enumerable: true,
configurable: true
});
return E;
}());
__decorate([
dec,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], E.prototype, "x", null);
var F = (function () {
function F() {
}
Object.defineProperty(F.prototype, "x", {
set: function (value) { },
enumerable: true,
configurable: true
});
return F;
}());
__decorate([
dec,
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], F.prototype, "x", null);
Loading