8000 Merge pull request #9175 from Microsoft/transforms-generators · microsoft/TypeScript@d4ad7f3 · GitHub
[go: up one dir, main page]

Skip to content

Commit d4ad7f3

Browse files
authored
Merge pull request #9175 from Microsoft/transforms-generators
[Transforms] Down-level transformations for Async Functions
2 parents 1c9df84 + c285767 commit d4ad7f3

File tree

406 files changed

+20386
-465
lines changed
  • Some content is hidden

    Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

    406 files changed

    +20386
    -465
    lines changed

    Jakefile.js

    Lines changed: 2 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -50,6 +50,7 @@ var compilerSources = [
    5050
    "transformers/module/module.ts",
    5151
    "transformers/jsx.ts",
    5252
    "transformers/es7.ts",
    53+
    "transformers/generators.ts",
    5354
    "transformers/es6.ts",
    5455
    "transformer.ts",
    5556
    "sourcemap.ts",
    @@ -82,6 +83,7 @@ var servicesSources = [
    8283
    "transformers/module/module.ts",
    8384
    "transformers/jsx.ts",
    8485
    "transformers/es7.ts",
    86+
    "transformers/generators.ts",
    8587
    "transformers/es6.ts",
    8688
    "transformer.ts",
    8789
    "sourcemap.ts",
    @@ -747,7 +749,6 @@ function writeTestConfigFile(tests, light, taskConfigsFolder, workerCount, stack
    747749
    taskConfigsFolder: taskConfigsFolder,
    748750
    stackTraceLimit: stackTraceLimit
    749751
    });
    750-
    console.log('Running tests with config: ' + testConfigContents);
    751752
    fs.writeFileSync('test.config', testConfigContents);
    752753
    }
    753754

    src/compiler/binder.ts

    Lines changed: 47 additions & 12 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1638,7 +1638,7 @@ namespace ts {
    16381638
    }
    16391639
    }
    16401640

    1641-
    function checkStrictModeNumericLiteral(node: LiteralExpression) {
    1641+
    function checkS F438 trictModeNumericLiteral(node: NumericLiteral) {
    16421642
    if (inStrictMode && node.isOctalLiteral) {
    16431643
    file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
    16441644
    }
    @@ -1786,7 +1786,7 @@ namespace ts {
    17861786
    case SyntaxKind.DeleteExpression:
    17871787
    return checkStrictModeDeleteExpression(<DeleteExpression>node);
    17881788
    case SyntaxKind.NumericLiteral:
    1789-
    return checkStrictModeNumericLiteral(<LiteralExpression>node);
    1789+
    return checkStrictModeNumericLiteral(<NumericLiteral>node);
    17901790
    case SyntaxKind.PostfixUnaryExpression:
    17911791
    return checkStrictModePostfixUnaryExpression(<PostfixUnaryExpression>node);
    17921792
    case SyntaxKind.PrefixUnaryExpression:
    @@ -2568,6 +2568,7 @@ namespace ts {
    25682568
    const modifierFlags = getModifierFlags(node);
    25692569
    const body = node.body;
    25702570
    const typeParameters = node.typeParameters;
    2571+
    const asteriskToken = node.asteriskToken;
    25712572

    25722573
    // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
    25732574
    // generic, or has a decorator.
    @@ -2578,6 +2579,11 @@ namespace ts {
    25782579
    transformFlags |= TransformFlags.AssertTypeScript;
    25792580
    }
    25802581

    2582+
    // Currently, we only support generators that were originally async function bodies.
    2583+
    if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
    2584+
    transformFlags |= TransformFlags.AssertGenerator;
    2585+
    }
    2586+
    25812587
    node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
    25822588
    return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
    25832589
    }
    @@ -2625,7 +2631,7 @@ namespace ts {
    26252631
    transformFlags = TransformFlags.AssertTypeScript;
    26262632
    }
    26272633
    else {
    2628-
    transformFlags = subtreeFlags;
    2634+
    transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
    26292635

    26302636
    // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
    26312637
    if (modifierFlags & ModifierFlags.Export) {
    @@ -2637,12 +2643,21 @@ namespace ts {
    26372643
    transformFlags |= TransformFlags.AssertTypeScript;
    26382644
    }
    26392645

    2640-
    // If a FunctionDeclaration has an asterisk token, is exported, or its
    2641-
    // subtree has marked the container as needing to capture the lexical `this`,
    2642-
    // then this node is ES6 syntax.
    2643-
    if (asteriskToken || (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask)) {
    2646+
    // If a FunctionDeclaration's subtree has marked the container as needing to capture the
    2647+
    // lexical this, or the function contains parameters with initializers, then this node is
    2648+
    // ES6 syntax.
    2649+
    if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
    26442650
    transformFlags |= TransformFlags.AssertES6;
    26452651
    }
    2652+
    2653+
    // If a FunctionDeclaration is generator function and is the body of a
    2654+
    // transformed async function, then this node can be transformed to a
    2655+
    // down-level generator.
    2656+
    // Currently we do not support transforming any other generator fucntions
    2657+
    // down level.
    2658+
    if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
    2659+
    transformFlags |= TransformFlags.AssertGenerator;
    2660+
    }
    26462661
    }
    26472662

    26482663
    node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
    @@ -2659,12 +2674,22 @@ namespace ts {
    26592674
    transformFlags |= TransformFlags.AssertTypeScript;
    26602675
    }
    26612676

    2662-
    // If a FunctionExpression contains an asterisk token, or its subtree has marked the container
    2663-
    // as needing to capture the lexical this, then this node is ES6 syntax.
    2664-
    if (asteriskToken || (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask)) {
    2677+
    // If a FunctionExpression's subtree has marked the container as needing to capture the
    2678+
    // lexical this, or the function contains parameters with initializers, then this node is
    2679+
    // ES6 syntax.
    2680+
    if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
    26652681
    transformFlags |= TransformFlags.AssertES6;
    26662682
    }
    26672683

    2684+
    // If a FunctionExpression is generator function and is the body of a
    2685+
    // transformed async function, then this node can be transformed to a
    2686< 10000 /code>+
    // down-level generator.
    2687+
    // Currently we do not support transforming any other generator fucntions
    2688+
    // down level.
    2689+
    if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) {
    2690+
    transformFlags |= TransformFlags.AssertGenerator;
    2691+
    }
    2692+
    26682693
    node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
    26692694
    return transformFlags & ~TransformFlags.FunctionExcludes;
    26702695
    }
    @@ -2794,7 +2819,7 @@ namespace ts {
    27942819
    }
    27952820

    27962821
    function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) {
    2797-
    let transformFlags = subtreeFlags;
    2822+
    let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
    27982823

    27992824
    if (subtreeFlags & TransformFlags.ContainsBindingPattern) {
    28002825
    transformFlags |= TransformFlags.AssertES6;
    @@ -2859,11 +2884,15 @@ namespace ts {
    28592884
    case SyntaxKind.TaggedTemplateExpression:
    28602885
    case SyntaxKind.ShorthandPropertyAssignment:
    28612886
    case SyntaxKind.ForOfStatement:
    2862-
    case SyntaxKind.YieldExpression:
    28632887
    // These nodes are ES6 syntax.
    28642888
    transformFlags |= TransformFlags.AssertES6;
    28652889
    break;
    28662890

    2891+
    case SyntaxKind.YieldExpression:
    2892+
    // This node is ES6 syntax.
    2893+
    transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
    2894+
    break;
    2895+
    28672896
    case SyntaxKind.AnyKeyword:
    28682897
    case SyntaxKind.NumberKeyword:
    28692898
    case SyntaxKind.NeverKeyword:
    @@ -2985,6 +3014,12 @@ namespace ts {
    29853014
    }
    29863015

    29873016
    break;
    3017+
    3018+
    case SyntaxKind.ReturnStatement:
    3019+
    case SyntaxKind.ContinueStatement:
    3020+
    case SyntaxKind.BreakStatement:
    3021+
    transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion;
    3022+
    break;
    29883023
    }
    29893024

    29903025
    node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;

    src/compiler/checker.ts

    Lines changed: 29 additions & 20 deletions
    Original file line numberDiff line numberDiff line change
    @@ -149,6 +149,7 @@ namespace ts {
    149149
    let getGlobalESSymbolConstructorSymbol: () => Symbol;
    150150

    151151
    let getGlobalPromiseConstructorSymbol: () => Symbol;
    152+
    let tryGetGlobalPromiseConstructorSymbol: () => Symbol;
    152153

    153154
    let globalObjectType: ObjectType;
    154155
    let globalFunctionType: ObjectType;
    @@ -8337,10 +8338,13 @@ namespace ts {
    83378338
    // can explicitly bound arguments objects
    83388339
    if (symbol === argumentsSymbol) {
    83398340
    const container = getContainingFunction(node);
    8340-
    if (container.kind === SyntaxKind.ArrowFunction) {
    8341-
    if (languageVersion < ScriptTarget.ES6) {
    8341+
    if (languageVersion < ScriptTarget.ES6) {
    8342+
    if (container.kind === SyntaxKind.ArrowFunction) {
    83428343
    error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
    83438344
    }
    8345+
    else if (hasModifier(container, ModifierFlags.Async)) {
    8346+
    error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method);
    8347+
    }
    83448348
    }
    83458349

    83468350
    if (node.flags & NodeFlags.AwaitContext) {
    @@ -12991,7 +12995,7 @@ namespace ts {
    1299112995
    return type;
    1299212996
    }
    1299312997

    12994-
    function checkNumericLiteral(node: LiteralExpression): Type {
    12998+
    function checkNumericLiteral(node: NumericLiteral): Type {
    1299512999
    // Grammar checking
    1299613000
    checkGrammarNumericLiteral(node);
    1299713001
    return numberType;
    @@ -13011,7 +13015,7 @@ namespace ts {
    1301113015
    case SyntaxKind.FalseKeyword:
    1301213016
    return booleanType;
    1301313017
    case SyntaxKind.NumericLiteral:
    13014-
    return checkNumericLiteral(<LiteralExpression>node);
    13018+
    return checkNumericLiteral(<NumericLiteral>node);
    1301513019
    case SyntaxKind.TemplateExpression:
    1301613020
    return checkTemplateExpression(<TemplateExpression>node);
    1301713021
    case SyntaxKind.StringLiteral:
    @@ -14194,7 +14198,7 @@ namespace ts {
    1419414198
    * @param returnType The return type of a FunctionLikeDeclaration
    1419514199
    * @param location The node on which to report the error.
    1419614200
    */
    14197-
    function checkCorrectPromiseType(returnType: Type, location: Node) {
    14201+
    function checkCorrectPromiseType(returnType: Type, location: Node, diagnostic: DiagnosticMessage, typeName?: string) {
    1419814202
    if (returnType === unknownType) {
    1419914203
    // The return type already had some other error, so we ignore and return
    1420014204
    // the unknown type.
    @@ -14213,7 +14217,7 @@ namespace ts {
    1421314217

    1421414218
    // The promise type was not a valid type reference to the global promise type, so we
    1421514219
    // report an error and return the unknown type.
    14216-
    error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
    14220+
    error(location, diagnostic, typeName);
    1421714221
    return unknownType;
    1421814222
    }
    1421914223

    @@ -14233,7 +14237,7 @@ namespace ts {
    1423314237
    function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
    1423414238
    if (languageVersion >= ScriptTarget.ES6) {
    1423514239
    const returnType = getTypeFromTypeNode(node.type);
    14236-
    return checkCorrectPromiseType(returnType, node.type);
    14240+
    return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
    1423714241
    }
    1423814242

    1423914243
    const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
    @@ -14279,19 +14283,19 @@ namespace ts {
    1427914283

    1428014284
    const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
    1428114285
    if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
    14286+
    // try to fall back to global promise type.
    1428214287
    const typeName = promiseConstructor
    1428314288
    ? symbolToString(promiseConstructor)
    1428414289
    : typeToString(promiseType);
    14285-
    error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
    14286-
    return unknownType;
    14290+
    return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
    1428714291
    }
    1428814292

    1428914293
    // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
    1429014294
    checkReturnTypeAnnotationAsExpression(node);
    1429114295

    1429214296
    // Validate the promise constructor type.
    1429314297
    const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
    14294-
    if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
    14298+
    if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
    1429514299
    return unknownType;
    1429614300
    }
    1429714301

    @@ -16272,7 +16276,7 @@ namespace ts {
    1627216276
    }
    1627316277
    return undefined;
    1627416278
    case SyntaxKind.NumericLiteral:
    16275-
    return +(<LiteralExpression>e).text;
    16279+
    return +(<NumericLiteral>e).text;
    1627616280
    case SyntaxKind.ParenthesizedExpression:
    1627716281
    return evalConstant((<ParenthesizedExpression>e).expression);
    1627816282
    case SyntaxKind.Identifier:
    @@ -17491,7 +17495,7 @@ namespace ts {
    1749117495
    if (objectType === unknownType) return undefined;
    1749217496
    const apparentType = getApparentType(objectType);
    1749317497
    if (apparentType === unknownType) return undefined;
    17494-
    return getPropertyOfType(apparentType, (<LiteralExpression>node).text);
    17498+
    return getPropertyOfType(apparentType, (<NumericLiteral>node).text);
    1749517499
    }
    1749617500
    break;
    1749717501
    }
    @@ -17976,6 +17980,11 @@ namespace ts {
    1797617980
    function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
    1797717981
    // Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
    1797817982
    const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
    17983+
    const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
    17984+
    if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
    17985+
    return TypeReferenceSerializationKind.Promise;
    17986+
    }
    17987+
    1797917988
    const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
    1798017989
    if (constructorType && isConstructorType(constructorType)) {
    1798117990
    return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
    @@ -17994,8 +18003,8 @@ namespace ts {
    1799418003
    else if (type.flags & TypeFlags.Any) {
    1799518004
    return TypeReferenceSerializationKind.ObjectType;
    1799618005
    }
    17997-
    else if (isTypeOfKind(type, TypeFlags.Void)) {
    17998-
    return TypeReferenceSerializationKind.VoidType;
    18006+
    else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
    18007+
    return TypeReferenceSerializationKind.VoidNullableOrNeverType;
    1799918008
    }
    1800018009
    else if (isTypeOfKind(type, TypeFlags.Boolean)) {
    1800118010
    return TypeReferenceSerializationKind.BooleanType;
    @@ -18293,6 +18302,7 @@ namespace ts {
    1829318302
    getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
    1829418303
    getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
    1829518304
    getGlobalPromiseConstructorSymbol = memoize(() => getGlobalValueSymbol("Promise"));
    18305+
    tryGetGlobalPromiseConstructorSymbol = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Value, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol());
    1829618306
    getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
    1829718307
    getGlobalThenableType = memoize(createThenableType);
    1829818308

    @@ -18348,6 +18358,9 @@ namespace ts {
    1834818358
    }
    1834918359
    if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
    1835018360
    verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
    18361+
    if (languageVersion < ScriptTarget.ES6) {
    18362+
    verifyHelperSymbol(exports, "__generator", SymbolFlags.Value);
    18363+
    }
    1835118364
    }
    1835218365
    }
    1835318366
    }
    @@ -18654,10 +18667,6 @@ namespace ts {
    1865418667
    }
    1865518668

    1865618669
    function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
    18657-
    if (languageVersion < ScriptTarget.ES6) {
    18658-
    return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher);
    18659-
    }
    18660-
    1866118670
    switch (node.kind) {
    1866218671
    case SyntaxKind.MethodDeclaration:
    1866318672
    case SyntaxKind.FunctionDeclaration:
    @@ -18967,7 +18976,7 @@ namespace ts {
    1896718976
    // Grammar checking for computedPropertyName and shorthandPropertyAssignment
    1896818977
    checkGrammarForInvalidQuestionMark(prop, (<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
    1896918978
    if (name.kind === SyntaxKind.NumericLiteral) {
    18970-
    checkGrammarNumericLiteral(<LiteralExpression>name);
    18979+
    checkGrammarNumericLiteral(<NumericLiteral>name);
    1897118980
    }
    1897218981
    currentKind = Property;
    1897318982
    }
    @@ -19489,7 +19498,7 @@ namespace ts {
    1948919498
    }
    1949019499
    }
    1949119500

    19492-
    function checkGrammarNumericLiteral(node: LiteralExpression): boolean {
    19501+
    function checkGrammarNumericLiteral(node: NumericLiteral): boolean {
    1949319502
    // Grammar checking
    1949419503
    if (node.isOctalLiteral && languageVersion >= ScriptTarget.ES5) {
    1949519504
    return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);

    0 commit comments

    Comments
     (0)
    0