Skip to content

Commit 980a894

Browse files
committed
Fix emit issue regarding null/undefined in type annotations
1 parent cfbfe32 commit 980a894

13 files changed

+393
-50
lines changed

src/compiler/binder.ts

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,9 @@ namespace ts {
23302330
case SyntaxKind.CallExpression:
23312331
return computeCallExpression(<CallExpression>node, subtreeFlags);
23322332

2333+
case SyntaxKind.NewExpression:
2334+
return computeNewExpression(<NewExpression>node, subtreeFlags);
2335+
23332336
case SyntaxKind.ModuleDeclaration:
23342337
return computeModuleDeclaration(<ModuleDeclaration>node, subtreeFlags);
23352338

@@ -2407,6 +2410,10 @@ namespace ts {
24072410
const expression = node.expression;
24082411
const expressionKind = expression.kind;
24092412

2413+
if (node.typeArguments) {
2414+
transformFlags |= TransformFlags.AssertTypeScript;
2415+
}
2416+
24102417
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression
24112418
|| isSuperOrSuperProperty(expression, expressionKind)) {
24122419
// If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6
@@ -2433,6 +2440,21 @@ namespace ts {
24332440
return false;
24342441
}
24352442

2443+
function computeNewExpression(node: NewExpression, subtreeFlags: TransformFlags) {
2444+
let transformFlags = subtreeFlags;
2445+
if (node.typeArguments) {
2446+
transformFlags |= TransformFlags.AssertTypeScript;
2447+
}
2448+
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) {
2449+
// If the this node contains a SpreadElementExpression then it is an ES6
2450+
// node.
2451+
transformFlags |= TransformFlags.AssertES6;
2452+
}
2453+
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
2454+
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
2455+
}
2456+
2457+
24362458
function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) {
24372459
let transformFlags = subtreeFlags;
24382460
const operatorTokenKind = node.operatorToken.kind;
@@ -2461,13 +2483,12 @@ namespace ts {
24612483
const initializer = node.initializer;
24622484
const dotDotDotToken = node.dotDotDotToken;
24632485

2464-
// If the parameter has a question token, then it is TypeScript syntax.
2465-
if (node.questionToken) {
2466-
transformFlags |= TransformFlags.AssertTypeScript;
2467-
}
2468-
2469-
// If the parameter's name is 'this', then it is TypeScript syntax.
2470-
if (subtreeFlags & TransformFlags.ContainsDecorators || isThisIdentifier(name)) {
2486+
// The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript
2487+
// syntax.
2488+
if (node.questionToken
2489+
|| node.type
2490+
|| subtreeFlags & TransformFlags.ContainsDecorators
2491+
|| isThisIdentifier(name)) {
24712492
transformFlags |= TransformFlags.AssertTypeScript;
24722493
}
24732494

@@ -2526,7 +2547,8 @@ namespace ts {
25262547
// TypeScript syntax.
25272548
// An exported declaration may be TypeScript syntax.
25282549
if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask)
2529-
|| (modifierFlags & ModifierFlags.Export)) {
2550+
|| (modifierFlags & ModifierFlags.Export)
2551+
|| node.typeParameters) {
25302552
transformFlags |= TransformFlags.AssertTypeScript;
25312553
}
25322554

@@ -2547,7 +2569,8 @@ namespace ts {
25472569

25482570
// A class with a parameter property assignment, property initializer, or decorator is
25492571
// TypeScript syntax.
2550-
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask) {
2572+
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask
2573+
|| node.typeParameters) {
25512574
transformFlags |= TransformFlags.AssertTypeScript;
25522575
}
25532576

@@ -2601,10 +2624,10 @@ namespace ts {
26012624

26022625
function computeConstructor(node: ConstructorDeclaration, subtreeFlags: TransformFlags) {
26032626
let transformFlags = subtreeFlags;
2604-
const body = node.body;
26052627

2606-
if (body === undefined) {
2607-
// An overload constructor is TypeScript syntax.
2628+
// TypeScript-specific modifiers and overloads are TypeScript syntax
2629+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2630+
|| !node.body) {
26082631
transformFlags |= TransformFlags.AssertTypeScript;
26092632
}
26102633

@@ -2615,22 +2638,19 @@ namespace ts {
26152638
function computeMethod(node: MethodDeclaration, subtreeFlags: TransformFlags) {
26162639
// A MethodDeclaration is ES6 syntax.
26172640
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
2618-
const modifierFlags = getModifierFlags(node);
2619-
const body = node.body;
2620-
const typeParameters = node.typeParameters;
2621-
const asteriskToken = node.asteriskToken;
2622-
2623-
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
2624-
// generic, or has a decorator.
2625-
if (!body
2626-
|| typeParameters
2627-
|| (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract))
2628-
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
2641+
2642+
// Decorators, TypeScript-specific modifiers, type parameters, type annotations, and
2643+
// overloads are TypeScript syntax.
2644+
if (node.decorators
2645+
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
2646+
|| node.typeParameters
2647+
|| node.type
2648+
|| !node.body) {
26292649
transformFlags |= TransformFlags.AssertTypeScript;
26302650
}
26312651

26322652
// Currently, we only support generators that were originally async function bodies.
2633-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2653+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
26342654
transformFlags |= TransformFlags.AssertGenerator;
26352655
}
26362656

@@ -2640,14 +2660,13 @@ namespace ts {
26402660

26412661
function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
26422662
let transformFlags = subtreeFlags;
2643-
const modifierFlags = getModifierFlags(node);
2644-
const body = node.body;
26452663

2646-
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
2647-
// generic, or has a decorator.
2648-
if (!body
2649-
|| (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract))
2650-
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
2664+
// Decorators, TypeScript-specific modifiers, type annotations, and overloads are
2665+
// TypeScript syntax.
2666+
if (node.decorators
2667+
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
2668+
|| node.type
2669+
|| !node.body) {
26512670
transformFlags |= TransformFlags.AssertTypeScript;
26522671
}
26532672

@@ -2673,7 +2692,6 @@ namespace ts {
26732692
let transformFlags: TransformFlags;
26742693
const modifierFlags = getModifierFlags(node);
26752694
const body = node.body;
2676-
const asteriskToken = node.asteriskToken;
26772695

26782696
if (!body || (modifierFlags & ModifierFlags.Ambient)) {
26792697
// An ambient declaration is TypeScript syntax.
@@ -2688,8 +2706,11 @@ namespace ts {
26882706
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES6;
26892707
}
26902708

2691-
// If a FunctionDeclaration is async, then it is TypeScript syntax.
2692-
if (modifierFlags & ModifierFlags.Async) {
2709+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2710+
// syntax.
2711+
if (modifierFlags & ModifierFlags.TypeScriptModifier
2712+
|| node.typeParameters
2713+
|| node.type) {
26932714
transformFlags |= TransformFlags.AssertTypeScript;
26942715
}
26952716

@@ -2705,7 +2726,7 @@ namespace ts {
27052726
// down-level generator.
27062727
// Currently we do not support transforming any other generator fucntions
27072728
// down level.
2708-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2729+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
27092730
transformFlags |= TransformFlags.AssertGenerator;
27102731
}
27112732
}
@@ -2716,11 +2737,12 @@ namespace ts {
27162737

27172738
function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) {
27182739
let transformFlags = subtreeFlags;
2719-
const modifierFlags = getModifierFlags(node);
2720-
const asteriskToken = node.asteriskToken;
27212740

2722-
// An async function expression is TypeScript syntax.
2723-
if (modifierFlags & ModifierFlags.Async) {
2741+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2742+
// syntax.
2743+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2744+
|| node.typeParameters
2745+
|| node.type) {
27242746
transformFlags |= TransformFlags.AssertTypeScript;
27252747
}
27262748

@@ -2736,7 +2758,7 @@ namespace ts {
27362758
// down-level generator.
27372759
// Currently we do not support transforming any other generator fucntions
27382760
// down level.
2739-
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
2761+
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
27402762
transformFlags |= TransformFlags.AssertGenerator;
27412763
}
27422764

@@ -2747,10 +2769,12 @@ namespace ts {
27472769
function computeArrowFunction(node: ArrowFunction, subtreeFlags: TransformFlags) {
27482770
// An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction.
27492771
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
2750-
const modifierFlags = getModifierFlags(node);
27512772

2752-
// An async arrow function is TypeScript syntax.
2753-
if (modifierFlags & ModifierFlags.Async) {
2773+
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
2774+
// syntax.
2775+
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
2776+
|| node.typeParameters
2777+
|| node.type) {
27542778
transformFlags |= TransformFlags.AssertTypeScript;
27552779
}
27562780

@@ -2787,6 +2811,11 @@ namespace ts {
27872811
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBindingPattern;
27882812
}
27892813

2814+
// Type annotations are TypeScript syntax.
2815+
if (node.type) {
2816+
transformFlags |= TransformFlags.AssertTypeScript;
2817+
}
2818+
27902819
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
27912820
return transformFlags & ~TransformFlags.NodeExcludes;
27922821
}

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/es6.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,7 @@ namespace ts {
14161416
if (getAccessor) {
14171417
const getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined);
14181418
setSourceMapRange(getterFunction, getSourceMapRange(getAccessor));
1419+
setEmitFlags(getterFunction, EmitFlags.NoLeadingComments);
14191420
const getter = createPropertyAssignment("get", getterFunction);
14201421
setCommentRange(getter, getCommentRange(getAccessor));
14211422
properties.push(getter);
@@ -1424,6 +1425,7 @@ namespace ts {
14241425
if (setAccessor) {
14251426
const setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined);
14261427
setSourceMapRange(setterFunction, getSourceMapRange(setAccessor));
1428+
setEmitFlags(setterFunction, EmitFlags.NoLeadingComments);
14271429
const setter = createPropertyAssignment("set", setterFunction);
14281430
setCommentRange(setter, getCommentRange(setAccessor));
14291431
properties.push(setter);

0 commit comments

Comments
 (0)