Skip to content

Commit

Permalink
[ts] Error on invalid type casts in JSX (#12221)
Browse files Browse the repository at this point in the history
  • Loading branch information
existentialism committed Oct 23, 2020
1 parent 8b579a2 commit c00bb14
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 18 deletions.
17 changes: 8 additions & 9 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -752,7 +752,7 @@ export default class ExpressionParser extends LValParser {
this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos;
} else {
this.toReferencedListDeep(node.arguments);
this.toReferencedArguments(node);

// We keep the old value if it isn't null, for cases like
// (x = async(yield)) => {}
Expand Down Expand Up @@ -791,6 +791,13 @@ export default class ExpressionParser extends LValParser {
return node;
}

toReferencedArguments(
node: N.CallExpression | N.OptionalCallExpression,
isParenthesizedExpr?: boolean,
) {
this.toReferencedListDeep(node.arguments, isParenthesizedExpr);
}

// MemberExpression [?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged]
// CallExpression [?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged]
parseTaggedTemplateExpression(
Expand Down Expand Up @@ -2057,14 +2064,6 @@ export default class ExpressionParser extends LValParser {
refExpressionErrors,
node,
);
if (canBePattern && !this.state.maybeInArrowParameters) {
// This could be an array pattern:
// ([a: string, b: string]) => {}
// In this case, we don't have to call toReferencedList. We will
// call it, if needed, when we are sure that it is a parenthesized
// expression by calling toReferencedListDeep.
this.toReferencedList(node.elements);
}
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
return this.finishNode(
node,
Expand Down
15 changes: 9 additions & 6 deletions packages/babel-parser/src/plugins/estree.js
Expand Up @@ -379,16 +379,19 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return node;
}
toReferencedListDeep(
exprList: $ReadOnlyArray<?N.Expression>,
isParenthesizedExpr?: boolean,
): void {
toReferencedArguments(
node:
| N.CallExpression
| N.OptionalCallExpression
| N.EstreeImportExpression,
/* isParenthesizedExpr?: boolean, */
) {
// ImportExpressions do not have an arguments array.
if (!exprList) {
if (node.type === "ImportExpression") {
return;
}
super.toReferencedListDeep(exprList, isParenthesizedExpr);
super.toReferencedArguments(node);
}
parseExport(node: N.Node) {
Expand Down
25 changes: 25 additions & 0 deletions packages/babel-parser/src/plugins/flow.js
Expand Up @@ -2233,6 +2233,31 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return exprList;
}

parseArrayLike(
close: TokenType,
canBePattern: boolean,
isTuple: boolean,
refExpressionErrors: ?ExpressionErrors,
): N.ArrayExpression | N.TupleExpression {
const node = super.parseArrayLike(
close,
canBePattern,
isTuple,
refExpressionErrors,
);

// This could be an array pattern:
// ([a: string, b: string]) => {}
// In this case, we don't have to call toReferencedList. We will
// call it, if needed, when we are sure that it is a parenthesized
// expression by calling toReferencedListDeep.
if (canBePattern && !this.state.maybeInArrowParameters) {
this.toReferencedList(node.elements);
}

return node;
}

checkLVal(
expr: N.Expression,
bindingType: BindingTypes = BIND_NONE,
Expand Down
10 changes: 10 additions & 0 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -1839,6 +1839,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return exprList;
}

parseArrayLike(...args): N.ArrayExpression | N.TupleExpression {
const node = super.parseArrayLike(...args);

if (node.type === "ArrayExpression") {
this.tsCheckForInvalidTypeCasts(node.elements);
}

return node;
}

parseSubscript(
base: N.Expression,
startPos: number,
Expand Down
@@ -1,2 +1,4 @@
(a:b);
(a:b,c:d);
[a:b];
[a:b, c:d];
@@ -1,14 +1,17 @@
{
"type": "File",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}},
"start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":11}},
"errors": [
"SyntaxError: Did not expect a type annotation here. (1:2)",
"SyntaxError: Did not expect a type annotation here. (2:2)",
"SyntaxError: Did not expect a type annotation here. (2:6)"
"SyntaxError: Did not expect a type annotation here. (2:6)",
"SyntaxError: Did not expect a type annotation here. (3:2)",
"SyntaxError: Did not expect a type annotation here. (4:2)",
"SyntaxError: Did not expect a type annotation here. (4:7)"
],
"program": {
"type": "Program",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}},
"start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":11}},
"sourceType": "module",
"interpreter": null,
"body": [
Expand Down Expand Up @@ -99,6 +102,92 @@
}
]
}
},
{
"type": "ExpressionStatement",
"start":18,"end":24,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":6}},
"expression": {
"type": "ArrayExpression",
"start":18,"end":23,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":5}},
"elements": [
{
"type": "TSTypeCastExpression",
"start":19,"end":22,"loc":{"start":{"line":3,"column":1},"end":{"line":3,"column":4}},
"expression": {
"type": "Identifier",
"start":19,"end":20,"loc":{"start":{"line":3,"column":1},"end":{"line":3,"column":2},"identifierName":"a"},
"name": "a"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":20,"end":22,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":4}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":21,"end":22,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":4}},
"typeName": {
"type": "Identifier",
"start":21,"end":22,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":4},"identifierName":"b"},
"name": "b"
}
}
}
}
]
}
},
{
"type": "ExpressionStatement",
"start":25,"end":36,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":11}},
"expression": {
"type": "ArrayExpression",
"start":25,"end":35,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":10}},
"elements": [
{
"type": "TSTypeCastExpression",
"start":26,"end":29,"loc":{"start":{"line":4,"column":1},"end":{"line":4,"column":4}},
"expression": {
"type": "Identifier",
"start":26,"end":27,"loc":{"start":{"line":4,"column":1},"end":{"line":4,"column":2},"identifierName":"a"},
"name": "a"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":27,"end":29,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":4}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":28,"end":29,"loc":{"start":{"line":4,"column":3},"end":{"line":4,"column":4}},
"typeName": {
"type": "Identifier",
"start":28,"end":29,"loc":{"start":{"line":4,"column":3},"end":{"line":4,"column":4},"identifierName":"b"},
"name": "b"
}
}
}
},
{
"type": "TSTypeCastExpression",
"start":31,"end":34,"loc":{"start":{"line":4,"column":6},"end":{"line":4,"column":9}},
"expression": {
"type": "Identifier",
"start":31,"end":32,"loc":{"start":{"line":4,"column":6},"end":{"line":4,"column":7},"identifierName":"c"},
"name": "c"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":32,"end":34,"loc":{"start":{"line":4,"column":7},"end":{"line":4,"column":9}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":33,"end":34,"loc":{"start":{"line":4,"column":8},"end":{"line":4,"column":9}},
"typeName": {
"type": "Identifier",
"start":33,"end":34,"loc":{"start":{"line":4,"column":8},"end":{"line":4,"column":9},"identifierName":"d"},
"name": "d"
}
}
}
}
]
}
}
],
"directives": []
Expand Down
@@ -0,0 +1,6 @@
function Foo() {
return (
<div propA={[ key: value ]} propsB={(a: b)} />
);
}

@@ -0,0 +1,142 @@
{
"type": "File",
"start":0,"end":85,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"errors": [
"SyntaxError: Did not expect a type annotation here. (3:21)",
"SyntaxError: Did not expect a type annotation here. (3:42)"
],
"program": {
"type": "Program",
"start":0,"end":85,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start":0,"end":85,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"id": {
"type": "Identifier",
"start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"Foo"},
"name": "Foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":15,"end":85,"loc":{"start":{"line":1,"column":15},"end":{"line":5,"column":1}},
"body": [
{
"type": "ReturnStatement",
"start":19,"end":83,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":4}},
"argument": {
"type": "JSXElement",
"start":32,"end":78,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":50}},
"extra": {
"parenthesized": true,
"parenStart": 26
},
"openingElement": {
"type": "JSXOpeningElement",
"start":32,"end":78,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":50}},
"name": {
"type": "JSXIdentifier",
"start":33,"end":36,"loc":{"start":{"line":3,"column":5},"end":{"line":3,"column":8}},
"name": "div"
},
"attributes": [
{
"type": "JSXAttribute",
"start":37,"end":59,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":31}},
"name": {
"type": "JSXIdentifier",
"start":37,"end":42,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":14}},
"name": "propA"
},
"value": {
"type": "JSXExpressionContainer",
"start":43,"end":59,"loc":{"start":{"line":3,"column":15},"end":{"line":3,"column":31}},
"expression": {
"type": "ArrayExpression",
"start":44,"end":58,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":30}},
"elements": [
{
"type": "TSTypeCastExpression",
"start":46,"end":56,"loc":{"start":{"line":3,"column":18},"end":{"line":3,"column":28}},
"expression": {
"type": "Identifier",
"start":46,"end":49,"loc":{"start":{"line":3,"column":18},"end":{"line":3,"column":21},"identifierName":"key"},
"name": "key"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":49,"end":56,"loc":{"start":{"line":3,"column":21},"end":{"line":3,"column":28}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":51,"end":56,"loc":{"start":{"line":3,"column":23},"end":{"line":3,"column":28}},
"typeName": {
"type": "Identifier",
"start":51,"end":56,"loc":{"start":{"line":3,"column":23},"end":{"line":3,"column":28},"identifierName":"value"},
"name": "value"
}
}
}
}
]
}
}
},
{
"type": "JSXAttribute",
"start":60,"end":75,"loc":{"start":{"line":3,"column":32},"end":{"line":3,"column":47}},
"name": {
"type": "JSXIdentifier",
"start":60,"end":66,"loc":{"start":{"line":3,"column":32},"end":{"line":3,"column":38}},
"name": "propsB"
},
"value": {
"type": "JSXExpressionContainer",
"start":67,"end":75,"loc":{"start":{"line":3,"column":39},"end":{"line":3,"column":47}},
"expression": {
"type": "TSTypeCastExpression",
"start":69,"end":73,"loc":{"start":{"line":3,"column":41},"end":{"line":3,"column":45}},
"extra": {
"parenthesized": true,
"parenStart": 68
},
"expression": {
"type": "Identifier",
"start":69,"end":70,"loc":{"start":{"line":3,"column":41},"end":{"line":3,"column":42},"identifierName":"a"},
"name": "a"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":70,"end":73,"loc":{"start":{"line":3,"column":42},"end":{"line":3,"column":45}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":72,"end":73,"loc":{"start":{"line":3,"column":44},"end":{"line":3,"column":45}},
"typeName": {
"type": "Identifier",
"start":72,"end":73,"loc":{"start":{"line":3,"column":44},"end":{"line":3,"column":45},"identifierName":"b"},
"name": "b"
}
}
}
}
}
}
],
"selfClosing": true
},
"closingElement": null,
"children": []
}
}
],
"directives": []
}
}
],
"directives": []
}
}

0 comments on commit c00bb14

Please sign in to comment.