Skip to content

Commit

Permalink
Fix some incorrect typeof parsing in flow
Browse files Browse the repository at this point in the history
  • Loading branch information
existentialism committed Nov 5, 2019
1 parent f544753 commit 794d723
Show file tree
Hide file tree
Showing 22 changed files with 2,787 additions and 24 deletions.
56 changes: 40 additions & 16 deletions packages/babel-parser/src/plugins/flow.js
Expand Up @@ -22,12 +22,15 @@ import {
SCOPE_OTHER,
} from "../util/scopeflags";

const reservedTypes = [
const reservedTypes = new Set([
"_",
"any",
"bool",
"boolean",
"empty",
"extends",
"false",
"interface",
"mixed",
"null",
"number",
Expand All @@ -36,10 +39,7 @@ const reservedTypes = [
"true",
"typeof",
"void",
"interface",
"extends",
"_",
];
]);

function isEsModuleType(bodyElement: N.Node): boolean {
return (
Expand Down Expand Up @@ -483,7 +483,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.FlowDeclare,
isClass?: boolean = false,
): void {
node.id = this.flowParseRestrictedIdentifier(/*liberal*/ !isClass);
node.id = this.flowParseRestrictedIdentifier(
/* liberal */ !isClass,
/* declaration */ true,
);

this.scope.declareName(
node.id.name,
Expand Down Expand Up @@ -557,21 +560,32 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

checkReservedType(word: string, startLoc: number) {
if (reservedTypes.indexOf(word) > -1) {
checkReservedType(word: string, startLoc: number, declaration?: boolean) {
if (!reservedTypes.has(word)) return;

if (declaration) {
this.raise(startLoc, `Cannot overwrite reserved type ${word}`);
return;
}

this.raise(startLoc, `Unexpected reserved type ${word}`);
}

flowParseRestrictedIdentifier(liberal?: boolean): N.Identifier {
this.checkReservedType(this.state.value, this.state.start);
flowParseRestrictedIdentifier(
liberal?: boolean,
declaration?: boolean,
): N.Identifier {
this.checkReservedType(this.state.value, this.state.start, declaration);
return this.parseIdentifier(liberal);
}

// Type aliases

flowParseTypeAlias(node: N.FlowTypeAlias): N.FlowTypeAlias {
node.id = this.flowParseRestrictedIdentifier();
node.id = this.flowParseRestrictedIdentifier(
/* liberal */ false,
/* declaration */ true,
);
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);

if (this.isRelational("<")) {
Expand All @@ -591,7 +605,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
declare: boolean,
): N.FlowOpaqueType {
this.expectContextual("type");
node.id = this.flowParseRestrictedIdentifier(/*liberal*/ true);
node.id = this.flowParseRestrictedIdentifier(
/* liberal */ true,
/* declaration */ true,
);
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);

if (this.isRelational("<")) {
Expand Down Expand Up @@ -1134,12 +1151,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
): N.FlowQualifiedTypeIdentifier {
startPos = startPos || this.state.start;
startLoc = startLoc || this.state.startLoc;
let node = id || this.parseIdentifier();
let node = id || this.parseIdentifier(true);

while (this.eat(tt.dot)) {
const node2 = this.startNodeAt(startPos, startLoc);
node2.qualification = node;
node2.id = this.parseIdentifier();
node2.id = this.flowParseRestrictedIdentifier(true);
node = this.finishNode(node2, "QualifiedTypeIdentifier");
}

Expand Down Expand Up @@ -2352,7 +2369,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
contextDescription: string,
): void {
specifier.local = hasTypeImportKind(node)
? this.flowParseRestrictedIdentifier(true)
? this.flowParseRestrictedIdentifier(
/* liberal */ true,
/* declaration */ true,
)
: this.parseIdentifier();

this.checkLVal(
Expand Down Expand Up @@ -2458,7 +2478,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}

if (nodeIsTypeImport || specifierIsTypeImport) {
this.checkReservedType(specifier.local.name, specifier.local.start);
this.checkReservedType(
specifier.local.name,
specifier.local.start,
/* declaration */ true,
);
}

if (isBinding && !nodeIsTypeImport && !specifierIsTypeImport) {
Expand Down
@@ -0,0 +1 @@
class Foo implements Bar, string {}
@@ -0,0 +1,155 @@
{
"type": "File",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 35
}
},
"errors": [
"SyntaxError: Unexpected reserved type string (1:26)"
],
"program": {
"type": "Program",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 35
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 35
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "Foo"
},
"name": "Foo"
},
"superClass": null,
"implements": [
{
"type": "ClassImplements",
"start": 21,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 21
},
"end": {
"line": 1,
"column": 24
}
},
"id": {
"type": "Identifier",
"start": 21,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 21
},
"end": {
"line": 1,
"column": 24
},
"identifierName": "Bar"
},
"name": "Bar"
},
"typeParameters": null
},
{
"type": "ClassImplements",
"start": 26,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 32
}
},
"id": {
"type": "Identifier",
"start": 26,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 32
},
"identifierName": "string"
},
"name": "string"
},
"typeParameters": null
}
],
"body": {
"type": "ClassBody",
"start": 33,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 33
},
"end": {
"line": 1,
"column": 35
}
},
"body": []
}
}
],
"directives": []
}
}
Expand Up @@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Cannot overwrite reserved type string (1:21)"
"SyntaxError: Unexpected reserved type string (1:21)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Cannot overwrite reserved type number (1:9)"
"SyntaxError: Unexpected reserved type number (1:9)"
],
"program": {
"type": "Program",
Expand Down
Expand Up @@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Cannot overwrite reserved type string (1:11)"
"SyntaxError: Unexpected reserved type string (1:11)"
],
"program": {
"type": "Program",
Expand Down
@@ -0,0 +1,2 @@
// @flow
const x: typeof interface = "hi";
@@ -0,0 +1,8 @@
{
"sourceType": "module",
"plugins": [
"jsx",
"flow"
],
"throws": "Unexpected token, expected \"{\" (2:26)"
}
@@ -0,0 +1,2 @@
// @flow
const x: typeof type.interface = "hi";

0 comments on commit 794d723

Please sign in to comment.