Skip to content
This repository has been archived by the owner on May 19, 2018. It is now read-only.

Commit

Permalink
Allow Flowtype's imports and exports when sourceType:script is set. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
loganfsmyth authored Oct 27, 2017
1 parent cb6082e commit e4bcd1d
Show file tree
Hide file tree
Showing 9 changed files with 477 additions and 17 deletions.
40 changes: 23 additions & 17 deletions src/parser/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,37 +129,34 @@ export default class StatementParser extends ExpressionParser {
case tt.semi:
return this.parseEmptyStatement(node);
case tt._export:
case tt._import:
case tt._import: {
if (
(this.hasPlugin("dynamicImport") &&
this.lookahead().type === tt.parenL) ||
(this.hasPlugin("importMeta") && this.lookahead().type === tt.dot)
)
break;

if (!this.options.allowImportExportEverywhere) {
if (!topLevel) {
this.raise(
this.state.start,
"'import' and 'export' may only appear at the top level",
);
}

if (!this.inModule) {
this.raise(
this.state.start,
`'import' and 'export' may appear only with 'sourceType: "module"'`,
);
}
if (!this.options.allowImportExportEverywhere && !topLevel) {
this.raise(
this.state.start,
"'import' and 'export' may only appear at the top level",
);
}

this.next();

let result;
if (starttype == tt._import) {
return this.parseImport(node);
result = this.parseImport(node);
} else {
return this.parseExport(node);
result = this.parseExport(node);
}

this.assertModuleNodeAllowed(node);

return result;
}
case tt.name:
if (this.state.value === "async") {
// peek ahead and see if next token is a function
Expand Down Expand Up @@ -193,6 +190,15 @@ export default class StatementParser extends ExpressionParser {
}
}

assertModuleNodeAllowed(node: N.Node): void {
if (!this.options.allowImportExportEverywhere && !this.inModule) {
this.raise(
node.start,
`'import' and 'export' may appear only with 'sourceType: "module"'`,
);
}
}

takeDecorators(node: N.HasDecorators): void {
const decorators = this.state.decoratorStack[
this.state.decoratorStack.length - 1
Expand Down
16 changes: 16 additions & 0 deletions src/plugins/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return node;
}

assertModuleNodeAllowed(node: N.Node) {
if (
(node.type === "ImportDeclaration" &&
(node.importKind === "type" || node.importKind === "typeof")) ||
(node.type === "ExportNamedDeclaration" &&
node.exportKind === "type") ||
(node.type === "ExportAllDeclaration" && node.exportKind === "type")
) {
// Allow Flowtype imports and exports in all conditions because
// Flow itself does not care about 'sourceType'.
return;
}

super.assertModuleNodeAllowed(node);
}

parseExport(node: N.ExportNamedDeclaration): N.ExportNamedDeclaration {
node = super.parseExport(node);
if (
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/flow/sourcetype-script/export-named/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type Foo = number;
export opaque type Foo = number;
167 changes: 167 additions & 0 deletions test/fixtures/flow/sourcetype-script/export-named/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
{
"type": "File",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"program": {
"type": "Program",
"start": 0,
"end": 58,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"sourceType": "script",
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"specifiers": [],
"source": null,
"exportKind": "type",
"declaration": {
"type": "TypeAlias",
"start": 7,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 25
}
},
"id": {
"type": "Identifier",
"start": 12,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "Foo"
},
"name": "Foo"
},
"typeParameters": null,
"right": {
"type": "NumberTypeAnnotation",
"start": 18,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 24
}
}
}
}
},
{
"type": "ExportNamedDeclaration",
"start": 26,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 32
}
},
"specifiers": [],
"source": null,
"exportKind": "type",
"declaration": {
"type": "OpaqueType",
"start": 33,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 7
},
"end": {
"line": 2,
"column": 32
}
},
"id": {
"type": "Identifier",
"start": 45,
"end": 48,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 22
},
"identifierName": "Foo"
},
"name": "Foo"
},
"typeParameters": null,
"supertype": null,
"impltype": {
"type": "NumberTypeAnnotation",
"start": 51,
"end": 57,
"loc": {
"start": {
"line": 2,
"column": 25
},
"end": {
"line": 2,
"column": 31
}
}
}
}
}
],
"directives": []
}
}
1 change: 1 addition & 0 deletions test/fixtures/flow/sourcetype-script/export-star/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type * from "foo";
70 changes: 70 additions & 0 deletions test/fixtures/flow/sourcetype-script/export-star/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"sourceType": "script",
"body": [
{
"type": "ExportAllDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"exportKind": "type",
"source": {
"type": "StringLiteral",
"start": 19,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 24
}
},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
}
}
],
"directives": []
}
}
2 changes: 2 additions & 0 deletions test/fixtures/flow/sourcetype-script/import/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { Foo } from "";
import typeof Foo2 from "";
Loading

0 comments on commit e4bcd1d

Please sign in to comment.