From 12dbdf03b1795e697ab69aab8e9a5fac40132ccb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 25 Jul 2022 17:17:27 -0400 Subject: [PATCH] Parse parameter decorators outside of Await context when appropriate (#50040) --- src/compiler/parser.ts | 2 +- ...ecoratorOnClassMethodParameter3.errors.txt | 15 +++++++ .../decoratorOnClassMethodParameter3.js | 41 +++++++++++++++++++ .../decoratorOnClassMethodParameter3.symbols | 24 +++++++++++ .../decoratorOnClassMethodParameter3.types | 25 +++++++++++ .../decoratorOnClassMethodParameter3.ts | 11 +++++ 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter3.errors.txt create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter3.js create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter3.symbols create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter3.types create mode 100644 tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 299a0fda38b..54d470938c0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3337,7 +3337,7 @@ namespace ts { // BindingElement[?Yield,?Await] // Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context. - const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : parseDecorators(); + const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : doOutsideOfAwaitContext(parseDecorators); if (token() === SyntaxKind.ThisKeyword) { const node = factory.createParameterDeclaration( diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter3.errors.txt b/tests/baselines/reference/decoratorOnClassMethodParameter3.errors.txt new file mode 100644 index 00000000000..fd0194a78b1 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter3.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts(5,23): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. + + +==== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/48509 + declare function dec(a: any): any; + function fn(value: Promise): any { + class Class { + async method(@dec(await value) arg: number) {} + ~~~~~ +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. + } + return Class + } + \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter3.js b/tests/baselines/reference/decoratorOnClassMethodParameter3.js new file mode 100644 index 00000000000..c7c1209af88 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter3.js @@ -0,0 +1,41 @@ +//// [decoratorOnClassMethodParameter3.ts] +// https://github.com/microsoft/TypeScript/issues/48509 +declare function dec(a: any): any; +function fn(value: Promise): any { + class Class { + async method(@dec(await value) arg: number) {} + } + return Class +} + + +//// [decoratorOnClassMethodParameter3.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 __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + 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) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function fn(value) { + class Class { + method(arg) { + return __awaiter(this, void 0, void 0, function* () { }); + } + } + __decorate([ + __param(0, dec(yield value)) + ], Class.prototype, "method", null); + return Class; +} diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter3.symbols b/tests/baselines/reference/decoratorOnClassMethodParameter3.symbols new file mode 100644 index 00000000000..628d4e67480 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter3.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts === +// https://github.com/microsoft/TypeScript/issues/48509 +declare function dec(a: any): any; +>dec : Symbol(dec, Decl(decoratorOnClassMethodParameter3.ts, 0, 0)) +>a : Symbol(a, Decl(decoratorOnClassMethodParameter3.ts, 1, 21)) + +function fn(value: Promise): any { +>fn : Symbol(fn, Decl(decoratorOnClassMethodParameter3.ts, 1, 34)) +>value : Symbol(value, Decl(decoratorOnClassMethodParameter3.ts, 2, 12)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + class Class { +>Class : Symbol(Class, Decl(decoratorOnClassMethodParameter3.ts, 2, 42)) + + async method(@dec(await value) arg: number) {} +>method : Symbol(Class.method, Decl(decoratorOnClassMethodParameter3.ts, 3, 15)) +>dec : Symbol(dec, Decl(decoratorOnClassMethodParameter3.ts, 0, 0)) +>value : Symbol(value, Decl(decoratorOnClassMethodParameter3.ts, 2, 12)) +>arg : Symbol(arg, Decl(decoratorOnClassMethodParameter3.ts, 4, 17)) + } + return Class +>Class : Symbol(Class, Decl(decoratorOnClassMethodParameter3.ts, 2, 42)) +} + diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter3.types b/tests/baselines/reference/decoratorOnClassMethodParameter3.types new file mode 100644 index 00000000000..21520b2097b --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter3.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts === +// https://github.com/microsoft/TypeScript/issues/48509 +declare function dec(a: any): any; +>dec : (a: any) => any +>a : any + +function fn(value: Promise): any { +>fn : (value: Promise) => any +>value : Promise + + class Class { +>Class : Class + + async method(@dec(await value) arg: number) {} +>method : (arg: number) => Promise +>dec(await value) : any +>dec : (a: any) => any +>await value : number +>value : Promise +>arg : number + } + return Class +>Class : typeof Class +} + diff --git a/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts new file mode 100644 index 00000000000..ccbf1672e4f --- /dev/null +++ b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter3.ts @@ -0,0 +1,11 @@ +// @target: es2015 +// @experimentaldecorators: true + +// https://github.com/microsoft/TypeScript/issues/48509 +declare function dec(a: any): any; +function fn(value: Promise): any { + class Class { + async method(@dec(await value) arg: number) {} + } + return Class +}