Skip to content

Commit d8936e9

Browse files
author
Kanchalai Tanglertsampan
committed
Correctly handle union of JSX element type
1 parent 2e8f16b commit d8936e9

File tree

1 file changed

+10
-27
lines changed

1 file changed

+10
-27
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="moduleNameResolver.ts"/>
1+
/// <reference path="moduleNameResolver.ts"/>
22
/// <reference path="binder.ts"/>
33

44
/* @internal */
@@ -590,7 +590,7 @@ namespace ts {
590590
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
591591
}
592592

593-
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
593+
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
594594
if (meaning) {
595595
const symbol = symbols.get(name);
596596
if (symbol) {
@@ -3362,7 +3362,8 @@ namespace ts {
33623362
const type = checkDeclarationInitializer(declaration);
33633363
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
33643364
}
3365-
else if (isJsxAttribute(declaration)) {
3365+
3366+
if (isJsxAttribute(declaration)) {
33663367
// if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true.
33673368
// I.e <Elem attr /> is sugar for <Elem attr={true} />
33683369
return trueType;
@@ -7003,7 +7004,8 @@ namespace ts {
70037004
// If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive.
70047005
return (<JsxAttribute>node).initializer && isContextSensitive((<JsxAttribute>node).initializer);
70057006
case SyntaxKind.JsxExpression:
7006-
return isContextSensitive((<JsxExpression>node).expression);
7007+
// It is possible to that node.expression is undefined (e.g <div x={} />)
7008+
return (<JsxExpression>node).expression && isContextSensitive((<JsxExpression>node).expression);
70077009
}
70087010

70097011
return false;
@@ -13258,10 +13260,7 @@ namespace ts {
1325813260
return false;
1325913261
}
1326013262
}
13261-
if (checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage)) {
13262-
return true;
13263-
}
13264-
return false;
13263+
return checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage);
1326513264
}
1326613265

1326713266
function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
@@ -13350,7 +13349,7 @@ namespace ts {
1335013349
return undefined;
1335113350
}
1335213351
else if (isJsxOpeningLikeElement(node)) {
13353-
args = node.attributes.properties.length > 0 ? [node.attributes] : [];
13352+
args = node.attributes.properties.length > 0 ? [node.attributes] : emptyArray;
1335413353
}
1335513354
else {
1335613355
args = node.arguments || emptyArray;
@@ -14164,23 +14163,7 @@ namespace ts {
1416414163
*/
1416514164
function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature {
1416614165
Debug.assert(!(elementType.flags & TypeFlags.Union));
14167-
const links = getNodeLinks(openingLikeElement);
14168-
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
14169-
// However, it is possible that either candidatesOutArray was not passed in the first time,
14170-
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
14171-
// to correctly fill the candidatesOutArray.
14172-
const cached = links.resolvedSignature;
14173-
if (cached && cached !== resolvingSignature && !candidatesOutArray) {
14174-
return cached;
14175-
}
14176-
links.resolvedSignature = resolvingSignature;
14177-
1417814166
const callSignature = resolveStatelessJsxOpeningLikeElement(openingLikeElement, elementType, candidatesOutArray);
14179-
links.resolvedSignature = callSignature;
14180-
// If signature resolution originated in control flow type analysis (for example to compute the
14181-
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
14182-
// types from the control flow analysis.
14183-
links.resolvedSignature = flowLoopStart === flowLoopCount ? callSignature : cached;
1418414167
return callSignature;
1418514168
}
1418614169

@@ -14198,8 +14181,7 @@ namespace ts {
1419814181
const types = (elementType as UnionType).types;
1419914182
let result: Signature;
1420014183
for (const type of types) {
14201-
// This is mainly to fill in all the candidates if there is one.
14202-
result = result && resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray);
14184+
result = result || resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray);
1420314185
}
1420414186

1420514187
return result;
@@ -14227,6 +14209,7 @@ namespace ts {
1422714209
return resolveDecorator(<Decorator>node, candidatesOutArray);
1422814210
case SyntaxKind.JsxOpeningElement:
1422914211
case SyntaxKind.JsxSelfClosingElement:
14212+
// This code-path is called by language service
1423014213
return resolveStatelessJsxOpeningLikeElement(<JsxOpeningLikeElement>node, checkExpression((<JsxOpeningLikeElement>node).tagName), candidatesOutArray);
1423114214
}
1423214215
Debug.fail("Branch in 'resolveSignature' should be unreachable.");

0 commit comments

Comments
 (0)