From f6cee27af9479236b3c2dc58460aea9cde728579 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 14 Jun 2016 06:11:00 -0700 Subject: [PATCH 1/2] Emit 'Promise' decorator metadata return type for async methods --- src/compiler/emitter.ts | 13 +++- .../reference/decoratorMetadataPromise.js | 59 +++++++++++++++++++ .../decoratorMetadataPromise.symbols | 33 +++++++++++ .../reference/decoratorMetadataPromise.types | 34 +++++++++++ .../compiler/decoratorMetadataPromise.ts | 14 +++++ 5 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/decoratorMetadataPromise.js create mode 100644 tests/baselines/reference/decoratorMetadataPromise.symbols create mode 100644 tests/baselines/reference/decoratorMetadataPromise.types create mode 100644 tests/cases/compiler/decoratorMetadataPromise.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e3f092257a3b4..e37a4d2d04832 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6156,9 +6156,16 @@ const _super = (function (geti, seti) { /** Serializes the return type of function. Used by the __metadata decorator for a method. */ function emitSerializedReturnTypeOfNode(node: Node) { - if (node && isFunctionLike(node) && (node).type) { - emitSerializedTypeNode((node).type); - return; + if (node && isFunctionLike(node)) { + const fn = node; + if (fn.type) { + emitSerializedTypeNode((node).type); + return; + } + else if (isAsyncFunctionLike(fn)) { + write("Promise"); + return; + } } write("void 0"); diff --git a/tests/baselines/reference/decoratorMetadataPromise.js b/tests/baselines/reference/decoratorMetadataPromise.js new file mode 100644 index 0000000000000..3ed8942033d60 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataPromise.js @@ -0,0 +1,59 @@ +//// [decoratorMetadataPromise.ts] + +declare const decorator: MethodDecorator; + +class A { + @decorator + async foo() {} + @decorator + async bar(): Promise { return 0; } + @decorator + baz(n: Promise): Promise { return n; } +} + + +//// [decoratorMetadataPromise.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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +class A { + foo() { + return __awaiter(this, void 0, void 0, function* () { }); + } + bar() { + return __awaiter(this, void 0, void 0, function* () { return 0; }); + } + baz(n) { return n; } +} +__decorate([ + decorator, + __metadata('design:type', Function), + __metadata('design:paramtypes', []), + __metadata('design:returntype', Promise) +], A.prototype, "foo", null); +__decorate([ + decorator, + __metadata('design:type', Function), + __metadata('design:paramtypes', []), + __metadata('design:returntype', Promise) +], A.prototype, "bar", null); +__decorate([ + decorator, + __metadata('design:type', Function), + __metadata('design:paramtypes', [Promise]), + __metadata('design:returntype', Promise) +], A.prototype, "baz", null); diff --git a/tests/baselines/reference/decoratorMetadataPromise.symbols b/tests/baselines/reference/decoratorMetadataPromise.symbols new file mode 100644 index 0000000000000..b0ebe05e8c1c4 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataPromise.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/decoratorMetadataPromise.ts === + +declare const decorator: MethodDecorator; +>decorator : Symbol(decorator, Decl(decoratorMetadataPromise.ts, 1, 13)) +>MethodDecorator : Symbol(MethodDecorator, Decl(lib.es5.d.ts, --, --)) + +class A { +>A : Symbol(A, Decl(decoratorMetadataPromise.ts, 1, 41)) + + @decorator +>decorator : Symbol(decorator, Decl(decoratorMetadataPromise.ts, 1, 13)) + + async foo() {} +>foo : Symbol(A.foo, Decl(decoratorMetadataPromise.ts, 3, 9)) + + @decorator +>decorator : Symbol(decorator, Decl(decoratorMetadataPromise.ts, 1, 13)) + + async bar(): Promise { return 0; } +>bar : Symbol(A.bar, Decl(decoratorMetadataPromise.ts, 5, 18)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) + + @decorator +>decorator : Symbol(decorator, Decl(decoratorMetadataPromise.ts, 1, 13)) + + baz(n: Promise): Promise { return n; } +>baz : Symbol(A.baz, Decl(decoratorMetadataPromise.ts, 7, 46)) +>n : Symbol(n, Decl(decoratorMetadataPromise.ts, 9, 8)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) +>n : Symbol(n, Decl(decoratorMetadataPromise.ts, 9, 8)) +} + diff --git a/tests/baselines/reference/decoratorMetadataPromise.types b/tests/baselines/reference/decoratorMetadataPromise.types new file mode 100644 index 0000000000000..900e751e84172 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataPromise.types @@ -0,0 +1,34 @@ +=== tests/cases/compiler/decoratorMetadataPromise.ts === + +declare const decorator: MethodDecorator; +>decorator : (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void +>MethodDecorator : (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void + +class A { +>A : A + + @decorator +>decorator : (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void + + async foo() {} +>foo : () => Promise + + @decorator +>decorator : (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void + + async bar(): Promise { return 0; } +>bar : () => Promise +>Promise : Promise +>0 : number + + @decorator +>decorator : (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void + + baz(n: Promise): Promise { return n; } +>baz : (n: Promise) => Promise +>n : Promise +>Promise : Promise +>Promise : Promise +>n : Promise +} + diff --git a/tests/cases/compiler/decoratorMetadataPromise.ts b/tests/cases/compiler/decoratorMetadataPromise.ts new file mode 100644 index 0000000000000..ef55e1946ded3 --- /dev/null +++ b/tests/cases/compiler/decoratorMetadataPromise.ts @@ -0,0 +1,14 @@ +// @experimentaldecorators: true +// @emitdecoratormetadata: true +// @target: es6 + +declare const decorator: MethodDecorator; + +class A { + @decorator + async foo() {} + @decorator + async bar(): Promise { return 0; } + @decorator + baz(n: Promise): Promise { return n; } +} From 33e4c7a9a3a4d2824c0967a615637df5429fa8d1 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 14 Jun 2016 06:50:44 -0700 Subject: [PATCH 2/2] Respond to PR comment --- src/compiler/emitter.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e37a4d2d04832..12377a0f26c52 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6157,12 +6157,11 @@ const _super = (function (geti, seti) { /** Serializes the return type of function. Used by the __metadata decorator for a method. */ function emitSerializedReturnTypeOfNode(node: Node) { if (node && isFunctionLike(node)) { - const fn = node; - if (fn.type) { + if ((node).type) { emitSerializedTypeNode((node).type); return; } - else if (isAsyncFunctionLike(fn)) { + else if (isAsyncFunctionLike(node)) { write("Promise"); return; }