From 2c46f9b6870348bd14973c1e5abb2f3ba893c084 Mon Sep 17 00:00:00 2001 From: Andrej Baran Date: Wed, 5 Oct 2016 17:09:58 +0200 Subject: [PATCH] Add ES8/ES2017 target (#10768) --- src/compiler/commandLineParser.ts | 2 ++ src/compiler/core.ts | 2 +- src/compiler/emitter.ts | 5 +++- src/compiler/transformer.ts | 6 +++-- src/compiler/transformers/ts.ts | 41 +++++++++++++++++++++++++------ src/compiler/types.ts | 4 ++- 6 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 648447ac26a..16d338cac6a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -262,7 +262,9 @@ namespace ts { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5, "es6": ScriptTarget.ES6, + "es8": ScriptTarget.ES8, "es2015": ScriptTarget.ES2015, + "es2017": ScriptTarget.ES2017, }), description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015, paramType: Diagnostics.VERSION, diff --git a/src/compiler/core.ts b/src/compiler/core.ts index e63bcbf8474..3f2cc619cb3 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1191,7 +1191,7 @@ namespace ts { export function getEmitModuleKind(compilerOptions: CompilerOptions) { return typeof compilerOptions.module === "number" ? compilerOptions.module : - getEmitScriptTarget(compilerOptions) === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.CommonJS; + getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.CommonJS; } /* @internal */ diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b3242e211de..b0e31278ff0 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2192,7 +2192,10 @@ const _super = (function (geti, seti) { helpersEmitted = true; } - if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) { + // Only emit __awaiter function when target ES5/ES6. + // Only emit __generator function when target ES5. + // For target ES8 and above, we can emit async/await as is. + if ((languageVersion < ScriptTarget.ES8) && (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions)) { writeLines(awaiterHelper); if (languageVersion < ScriptTarget.ES6) { writeLines(generatorHelper); diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 92407af2bb9..415a9ecd1d7 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -115,7 +115,9 @@ namespace ts { transformers.push(transformJsx); } - transformers.push(transformES7); + if (languageVersion < ScriptTarget.ES8) { + transformers.push(transformES7); + } if (languageVersion < ScriptTarget.ES6) { transformers.push(transformES6); @@ -339,4 +341,4 @@ namespace ts { return statements; } } -} \ No newline at end of file +} diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index f6e8074cb07..40b9e7f64e1 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -240,11 +240,14 @@ namespace ts { // ES6 export and default modifiers are elided when inside a namespace. return currentNamespace ? undefined : node; + case SyntaxKind.AsyncKeyword: + // Async keyword is not elided for target ES8 + return languageVersion < ScriptTarget.ES8 ? undefined : node; + case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsyncKeyword: case SyntaxKind.ConstKeyword: case SyntaxKind.DeclareKeyword: case SyntaxKind.ReadonlyKeyword: @@ -2223,6 +2226,14 @@ namespace ts { /*location*/ node ); + // Add ES8 async function expression modifier + // Not sure this is the right place? Might be better to move this + // into createFunctionExpression itself. + if ((languageVersion >= ScriptTarget.ES8) && isAsyncFunctionLike(node)) { + const funcModifiers = visitNodes(node.modifiers, visitor, isModifier); + func.modifiers = createNodeArray(funcModifiers); + } + setOriginalNode(func, node); return func; @@ -2235,7 +2246,7 @@ namespace ts { */ function visitArrowFunction(node: ArrowFunction) { const func = createArrowFunction( - /*modifiers*/ undefined, + visitNodes(node.modifiers, visitor, isModifier), /*typeParameters*/ undefined, visitNodes(node.parameters, visitor, isParameter), /*type*/ undefined, @@ -2250,7 +2261,7 @@ namespace ts { } function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody { - if (isAsyncFunctionLike(node)) { + if (isAsyncFunctionLike(node) && languageVersion < ScriptTarget.ES8) { return transformAsyncFunctionBody(node); } @@ -2270,7 +2281,7 @@ namespace ts { } function transformConciseBody(node: ArrowFunction): ConciseBody { - if (isAsyncFunctionLike(node)) { + if (isAsyncFunctionLike(node) && languageVersion < ScriptTarget.ES8) { return transformAsyncFunctionBody(node); } @@ -2453,14 +2464,28 @@ namespace ts { * @param node The await expression node. */ function visitAwaitExpression(node: AwaitExpression): Expression { + const targetAtLeastES8 = languageVersion >= ScriptTarget.ES8; return setOriginalNode( - createYield( + targetAtLeastES8 ? createAwaitExpression() : createYieldExpression(), + node + ); + + function createAwaitExpression() { + const awaitExpression = createAwait( + visitNode(node.expression, visitor, isExpression), + /*location*/ node + ); + return awaitExpression; + } + + function createYieldExpression() { + const yieldExpression = createYield( /*asteriskToken*/ undefined, visitNode(node.expression, visitor, isExpression), /*location*/ node - ), - node - ); + ); + return yieldExpression; + } } /** diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4a4a25fd627..5b193beb155 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2831,8 +2831,10 @@ namespace ts { ES3 = 0, ES5 = 1, ES6 = 2, + ES8 = 3, ES2015 = ES6, - Latest = ES6, + ES2017 = ES8, + Latest = ES8, } export const enum LanguageVariant {