From 72b1f0a56415101b4921a9968ad2ef10e376f529 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Wed, 31 Oct 2018 16:36:45 -0700 Subject: [PATCH] fix: Do not allow TypeCastExpressions w/o parens --- .../babel-parser/src/parser/expression.js | 2 +- packages/babel-parser/src/parser/lval.js | 1 + packages/babel-parser/src/plugins/flow.js | 36 ++++++------------- .../babel-parser/src/plugins/typescript.js | 1 + .../fail-in-calls-with-one-arg/input.js | 1 + .../fail-in-calls-with-one-arg/options.json | 3 ++ .../flow/typecasts/fail-in-calls/input.js | 1 + .../flow/typecasts/fail-in-calls/options.json | 3 ++ .../typecasts/fail-without-parens/input.js | 1 + .../fail-without-parens/options.json | 3 ++ scripts/tests/flow/flow_tests_whitelist.txt | 1 - 11 files changed, 26 insertions(+), 27 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/input.js create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/options.json create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/input.js create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/options.json create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/input.js create mode 100644 packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/options.json diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index dae74bf3d614..8d7677d4bea8 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -804,7 +804,7 @@ export default class ExpressionParser extends LValParser { this.state.yieldInPossibleArrowParameters = null; const params = [this.parseIdentifier()]; this.expect(tt.arrow); - // let foo = bar => {}; + // let foo = async bar => {}; this.parseArrowExpression(node, params, true); this.state.yieldInPossibleArrowParameters = oldYield; return node; diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index 46234dade3a9..b9e023cbd3d2 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -177,6 +177,7 @@ export default class LValParser extends NodeUtils { toReferencedList( exprList: $ReadOnlyArray, + isInParens?: boolean, // eslint-disable-line no-unused-vars ): $ReadOnlyArray { return exprList; } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index 6ba0ddd8651b..617a115579bc 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -1976,40 +1976,26 @@ export default (superClass: Class): Class => // type casts that we've found that are illegal in this context toReferencedList( exprList: $ReadOnlyArray, + isInParens?: boolean, ): $ReadOnlyArray { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; - if (expr && expr._exprListItem && expr.type === "TypeCastExpression") { - this.raise(expr.start, "Unexpected type cast"); + if ( + expr && + expr.type === "TypeCastExpression" && + (!expr.extra || !expr.extra.parenthesized) && + (exprList.length > 1 || !isInParens) + ) { + this.raise( + expr.typeAnnotation.start, + "The type cast expression is expected to be wrapped with parenthesis", + ); } } return exprList; } - // parse an item inside a expression list eg. `(NODE, NODE)` where NODE represents - // the position where this function is called - parseExprListItem( - allowEmpty: ?boolean, - refShorthandDefaultPos: ?Pos, - refNeedsArrowPos: ?Pos, - ): ?N.Expression { - const container = this.startNode(); - const node = super.parseExprListItem( - allowEmpty, - refShorthandDefaultPos, - refNeedsArrowPos, - ); - if (this.match(tt.colon)) { - container._exprListItem = true; - container.expression = node; - container.typeAnnotation = this.flowParseTypeAnnotation(); - return this.finishNode(container, "TypeCastExpression"); - } else { - return node; - } - } - checkLVal( expr: N.Expression, isBinding: ?boolean, diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index bd3d88d9ac1f..bd63e93407c2 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -2151,6 +2151,7 @@ export default (superClass: Class): Class => toReferencedList( exprList: $ReadOnlyArray, + isInParens?: boolean, // eslint-disable-line no-unused-vars ): $ReadOnlyArray { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/input.js b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/input.js new file mode 100644 index 000000000000..33bdb94b5828 --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/input.js @@ -0,0 +1 @@ +funccall(b: string); diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/options.json b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/options.json new file mode 100644 index 000000000000..e4012a53ad5d --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls-with-one-arg/options.json @@ -0,0 +1,3 @@ +{ + "throws": "The type cast expression is expected to be wrapped with parenthesis (1:10)" +} diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/input.js b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/input.js new file mode 100644 index 000000000000..56208a86b2b8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/input.js @@ -0,0 +1 @@ +funccall(a, b: string); diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/options.json b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/options.json new file mode 100644 index 000000000000..3f861de320eb --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-in-calls/options.json @@ -0,0 +1,3 @@ +{ + "throws": "The type cast expression is expected to be wrapped with parenthesis (1:13)" +} diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/input.js b/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/input.js new file mode 100644 index 000000000000..767b0cba53b8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/input.js @@ -0,0 +1 @@ +(A, B: T) diff --git a/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/options.json b/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/options.json new file mode 100644 index 000000000000..847e987ef0af --- /dev/null +++ b/packages/babel-parser/test/fixtures/flow/typecasts/fail-without-parens/options.json @@ -0,0 +1,3 @@ +{ + "throws": "The type cast expression is expected to be wrapped with parenthesis (1:5)" +} diff --git a/scripts/tests/flow/flow_tests_whitelist.txt b/scripts/tests/flow/flow_tests_whitelist.txt index e9f6d0bc4262..83bd8efbb415 100644 --- a/scripts/tests/flow/flow_tests_whitelist.txt +++ b/scripts/tests/flow/flow_tests_whitelist.txt @@ -31,7 +31,6 @@ types/annotations_in_comments_invalid/migrated_0003.js types/annotations/void_is_reserved_param.js types/member/reserved_words.js types/parameter_defaults/migrated_0032.js -types/typecasts_invalid/migrated_0001.js class_method_kinds/polymorphic_getter.js numbers/underscored_bin.js numbers/underscored_float.js