Skip to content

Commit 65b1cf6

Browse files
authored
Merge pull request #11653 from Microsoft/fix11295
Fix emit issue regarding null/undefined in type annotations
2 parents 63160de + db76a9c commit 65b1cf6

13 files changed

+642
-48
lines changed

src/compiler/binder.ts

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,9 @@ namespace ts {
23512351
case SyntaxKind.CallExpression:
23522352
return computeCallExpression(<CallExpression>node, subtreeFlags);
23532353

2354+
case SyntaxKind.NewExpression:
2355+
return computeNewExpression(<NewExpression>node, subtreeFlags);
2356+
23542357
case SyntaxKind.ModuleDeclaration:
23552358
return computeModuleDeclaration(<ModuleDeclaration>node, subtreeFlags);
23562359

@@ -2428,6 +2431,10 @@ namespace ts {
24282431
const expression = node.expression;
24292432
const expressionKind = expression.kind;
24302433

2434+
if (node.typeArguments) {
2435+
transformFlags |= TransformFlags.AssertTypeScript;
2436+
}
2437+
24312438
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression
24322439
|| isSuperOrSuperProperty(expression, expressionKind)) {
24332440
// If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6
@@ -2454,6 +2461,21 @@ namespace ts {
24542461
return false;
24552462
}
24562463

2464+
function computeNewExpression(node: NewExpression, subtreeFlags: TransformFlags) {
2465+
let transformFlags = subtreeFlags;
2466+
if (node.typeArguments) {
2467+
transformFlags |= TransformFlags.AssertTypeScript;
2468+
}
2469+
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) {
2470+
// If the this node contains a SpreadElementExpression then it is an ES6
2471+
// node.
2472+
transformFlags |= TransformFlags.AssertES2015;
2473+
}
2474+
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
2475+
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
2476+
}
2477+
2478+
24572479
function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) {
24582480
let transformFlags = subtreeFlags;
24592481
const operatorTokenKind = node.operatorToken.kind;
@@ -2482,13 +2504,12 @@ namespace ts {
24822504
const initializer = node.initializer;
24832505
const dotDotDotToken = node.dotDotDotToken;
24842506

2485-
// If the parameter has a question token, then it is TypeScript syntax.
2486-
if (node.questionToken) {
2487-
transformFlags |= TransformFlags.AssertTypeScript;
2488-
}
2489-
2490-
// If the parameter's name is 'this', then it is TypeScript syntax.
2491-
if (subtreeFlags & TransformFlags.ContainsDecorators || isThisIdentifier(name)) {
2507+
// The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript
2508+
// syntax.
2509+
if (node.questionToken
2510+
|| node.type
2511+
|| subtreeFlags & TransformFlags.ContainsDecorators
2512+
|| isThisIdentifier(name)) {
24922513
transformFlags |= TransformFlags.AssertTypeScript;
24932514
}
24942515

@@ -2547,7 +2568,8 @@ namespace ts {
25472568
// TypeScript syntax.
25482569
// An exported declaration may be TypeScript syntax.
25492570
if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask)
2550-
|| (modifierFlags & ModifierFlags.Export)) {
2571+
|| (modifierFlags & ModifierFlags.Export)
2572+
|| node.typeParameters) {
25512573
transformFlags |= TransformFlags.AssertTypeScript;
25522574
}
25532575

@@ -2568,7 +2590,8 @@ namespace ts {
25682590

25692591
// A class with a parameter property assignment, property initializer, or decorator is
25702592
// TypeScript syntax.
2571-
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask) {
2593+
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask
2594+
|| node.typeParameters) {
25722595
transformFlags |= TransformFlags.AssertTypeScript;
25732596
}
25742597

@@ -2622,10 +2645,10 @@ namespace ts {
26222645

26232646
function computeConstructor(node: ConstructorDeclaration, subtreeFlags: TransformFlags) {
26242647
let transformFlags = subtreeFlags;
2625-
const body = node.body;
26262648

2627-
if (body === undefined) {
2628-
// An overload constructor is TypeScript syntax.
2649+
// TypeScript-specific modifiers and overloads are TypeScript syntax
2650+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2651+
|| !node.body) {
26292652
transformFlags |= TransformFlags.AssertTypeScript;
26302653
}
26312654

@@ -2636,27 +2659,24 @@ namespace ts {
26362659
function computeMethod(node: MethodDeclaration, subtreeFlags: TransformFlags) {
26372660
// A MethodDeclaration is ES6 syntax.
26382661
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
2639-
const modifierFlags = getModifierFlags(node);
2640-
const body = node.body;
2641-
const typeParameters = node.typeParameters;
2642-
const asteriskToken = node.asteriskToken;
2643-
2644-
// A MethodDeclaration is TypeScript syntax if it is either abstract, overloaded,
2645-
// generic, or has a decorator.
2646-
if (!body
2647-
|| typeParameters
2648-
|| (modifierFlags & ModifierFlags.Abstract)
2649-
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
2662+
2663+
// Decorators, TypeScript-specific modifiers, type parameters, type annotations, and
2664+
// overloads are TypeScript syntax.
2665+
if (node.decorators
2666+
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
2667+
|| node.typeParameters
2668+
|| node.type
2669+
|| !node.body) {
26502670
transformFlags |= TransformFlags.AssertTypeScript;
26512671
}
26522672

26532673
// An async method declaration is ES2017 syntax.
2654-
if (modifierFlags & ModifierFlags.Async) {
2674+
if (hasModifier(node, ModifierFlags.Async)) {
26552675
transformFlags |= TransformFlags.AssertES2017;
26562676
}
26572677

26582678
// Currently, we only support generators that were originally async function bodies.
2659-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2679+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
26602680
transformFlags |= TransformFlags.AssertGenerator;
26612681
}
26622682

@@ -2666,14 +2686,13 @@ namespace ts {
26662686

26672687
function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
26682688
let transformFlags = subtreeFlags;
2669-
const modifierFlags = getModifierFlags(node);
2670-
const body = node.body;
26712689

2672-
// An accessor is TypeScript syntax if it is either abstract, overloaded,
2673-
// generic, or has a decorator.
2674-
if (!body
2675-
|| (modifierFlags & ModifierFlags.Abstract)
2676-
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
2690+
// Decorators, TypeScript-specific modifiers, type annotations, and overloads are
2691+
// TypeScript syntax.
2692+
if (node.decorators
2693+
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
2694+
|| node.type
2695+
|| !node.body) {
26772696
transformFlags |= TransformFlags.AssertTypeScript;
26782697
}
26792698

@@ -2699,7 +2718,6 @@ namespace ts {
26992718
let transformFlags: TransformFlags;
27002719
const modifierFlags = getModifierFlags(node);
27012720
const body = node.body;
2702-
const asteriskToken = node.asteriskToken;
27032721

27042722
if (!body || (modifierFlags & ModifierFlags.Ambient)) {
27052723
// An ambient declaration is TypeScript syntax.
@@ -2714,6 +2732,14 @@ namespace ts {
27142732
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES2015;
27152733
}
27162734

2735+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2736+
// syntax.
2737+
if (modifierFlags & ModifierFlags.TypeScriptModifier
2738+
|| node.typeParameters
2739+
|| node.type) {
2740+
transformFlags |= TransformFlags.AssertTypeScript;
2741+
}
2742+
27172743
// An async function declaration is ES2017 syntax.
27182744
if (modifierFlags & ModifierFlags.Async) {
27192745
transformFlags |= TransformFlags.AssertES2017;
@@ -2731,7 +2757,7 @@ namespace ts {
27312757
// down-level generator.
27322758
// Currently we do not support transforming any other generator fucntions
27332759
// down level.
2734-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2760+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
27352761
transformFlags |= TransformFlags.AssertGenerator;
27362762
}
27372763
}
@@ -2742,11 +2768,17 @@ namespace ts {
27422768

27432769
function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) {
27442770
let transformFlags = subtreeFlags;
2745-
const modifierFlags = getModifierFlags(node);
2746-
const asteriskToken = node.asteriskToken;
2771+
2772+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2773+
// syntax.
2774+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2775+
|| node.typeParameters
2776+
|| node.type) {
2777+
transformFlags |= TransformFlags.AssertTypeScript;
2778+
}
27472779

27482780
// An async function expression is ES2017 syntax.
2749-
if (modifierFlags & ModifierFlags.Async) {
2781+
if (hasModifier(node, ModifierFlags.Async)) {
27502782
transformFlags |= TransformFlags.AssertES2017;
27512783
}
27522784

@@ -2762,7 +2794,7 @@ namespace ts {
27622794
// down-level generator.
27632795
// Currently we do not support transforming any other generator fucntions
27642796
// down level.
2765-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2797+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
27662798
transformFlags |= TransformFlags.AssertGenerator;
27672799
}
27682800

@@ -2773,10 +2805,17 @@ namespace ts {
27732805
function computeArrowFunction(node: ArrowFunction, subtreeFlags: TransformFlags) {
27742806
// An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction.
27752807
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
2776-
const modifierFlags = getModifierFlags(node);
2808+
2809+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2810+
// syntax.
2811+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2812+
|| node.typeParameters
2813+
|| node.type) {
2814+
transformFlags |= TransformFlags.AssertTypeScript;
2815+
}
27772816

27782817
// An async arrow function is ES2017 syntax.
2779-
if (modifierFlags & ModifierFlags.Async) {
2818+
if (hasModifier(node, ModifierFlags.Async)) {
27802819
transformFlags |= TransformFlags.AssertES2017;
27812820
}
27822821

@@ -2813,6 +2852,11 @@ namespace ts {
28132852
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
28142853
}
28152854

2855+
// Type annotations are TypeScript syntax.
2856+
if (node.type) {
2857+
transformFlags |= TransformFlags.AssertTypeScript;
2858+
}
2859+
28162860
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
28172861
return transformFlags & ~TransformFlags.NodeExcludes;
28182862
}

src/compiler/emitter.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,15 +504,29 @@ const _super = (function (geti, seti) {
504504

505505
// Contextual keywords
506506
case SyntaxKind.AbstractKeyword:
507+
case SyntaxKind.AsKeyword:
507508
case SyntaxKind.AnyKeyword:
508509
case SyntaxKind.AsyncKeyword:
510+
case SyntaxKind.AwaitKeyword:
509511
case SyntaxKind.BooleanKeyword:
512+
case SyntaxKind.ConstructorKeyword:
510513
case SyntaxKind.DeclareKeyword:
511-
case SyntaxKind.NumberKeyword:
514+
case SyntaxKind.GetKeyword:
515+
case SyntaxKind.IsKeyword:
516+
case SyntaxKind.ModuleKeyword:
517+
case SyntaxKind.NamespaceKeyword:
518+
case SyntaxKind.NeverKeyword:
512519
case SyntaxKind.ReadonlyKeyword:
520+
case SyntaxKind.RequireKeyword:
521+
case SyntaxKind.NumberKeyword:
522+
case SyntaxKind.SetKeyword:
513523
case SyntaxKind.StringKeyword:
514524
case SyntaxKind.SymbolKeyword:
525+
case SyntaxKind.TypeKeyword:
526+
case SyntaxKind.UndefinedKeyword:
527+
case SyntaxKind.FromKeyword:
515528
case SyntaxKind.GlobalKeyword:
529+
case SyntaxKind.OfKeyword:
516530
writeTokenText(kind);
517531
return;
518532

@@ -1198,12 +1212,14 @@ const _super = (function (geti, seti) {
11981212

11991213
function emitCallExpression(node: CallExpression) {
12001214
emitExpression(node.expression);
1215+
emitTypeArguments(node, node.typeArguments);
12011216
emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments);
12021217
}
12031218

12041219
function emitNewExpression(node: NewExpression) {
12051220
write("new ");
12061221
emitExpression(node.expression);
1222+
emitTypeArguments(node, node.typeArguments);
12071223
emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments);
12081224
}
12091225

@@ -1575,6 +1591,7 @@ const _super = (function (geti, seti) {
15751591

15761592
function emitVariableDeclaration(node: VariableDeclaration) {
15771593
emit(node.name);
1594+
emitWithPrefix(": ", node.type);
15781595
emitExpressionWithPrefix(" = ", node.initializer);
15791596
}
15801597

src/compiler/transformers/es2015.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,7 @@ namespace ts {
14171417
if (getAccessor) {
14181418
const getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined);
14191419
setSourceMapRange(getterFunction, getSourceMapRange(getAccessor));
1420+
setEmitFlags(getterFunction, EmitFlags.NoLeadingComments);
14201421
const getter = createPropertyAssignment("get", getterFunction);
14211422
setCommentRange(getter, getCommentRange(getAccessor));
14221423
properties.push(getter);
@@ -1425,6 +1426,7 @@ namespace ts {
14251426
if (setAccessor) {
14261427
const setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined);
14271428
setSourceMapRange(setterFunction, getSourceMapRange(setAccessor));
1429+
setEmitFlags(setterFunction, EmitFlags.NoLeadingComments);
14281430
const setter = createPropertyAssignment("set", setterFunction);
14291431
setCommentRange(setter, getCommentRange(setAccessor));
14301432
properties.push(setter);

0 commit comments

Comments
 (0)