diff --git a/src/parser/statement.js b/src/parser/statement.js index 63d3d315e9..821021e57e 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -1016,7 +1016,7 @@ pp.parseExportSpecifiers = function () { // Parses import declaration. pp.parseImport = function (node) { - this.next(); + this.eat(tt._import); // import '...' if (this.match(tt.string)) { diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 94d5ae4b97..90b6e13f85 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -95,11 +95,22 @@ pp.flowParseDeclareModule = function (node) { const body = bodyNode.body = []; this.expect(tt.braceL); while (!this.match(tt.braceR)) { - const node2 = this.startNode(); + let bodyNode = this.startNode(); - this.expectContextual("declare", "Unexpected token. Only declares are allowed inside declare module"); + if (this.match(tt._import)) { + const lookahead = this.lookahead(); + if (lookahead.value !== "type" && lookahead.value !== "typeof") { + this.unexpected(null, "Imports within a `declare module` body must always be `import type` or `import typeof`"); + } - body.push(this.flowParseDeclare(node2)); + this.parseImport(bodyNode); + } else { + this.expectContextual("declare", "Only declares and type imports are allowed inside declare module"); + + bodyNode = this.flowParseDeclare(bodyNode, true); + } + + body.push(bodyNode); } this.expect(tt.braceR); diff --git a/test/fixtures/flow/declare-module/8/options.json b/test/fixtures/flow/declare-module/8/options.json index ae5e7790e2..32826163f1 100644 --- a/test/fixtures/flow/declare-module/8/options.json +++ b/test/fixtures/flow/declare-module/8/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token. Only declares are allowed inside declare module (2:2)" + "throws": "Only declares and type imports are allowed inside declare module (2:2)" } diff --git a/test/fixtures/flow/declare-module/import/actual.js b/test/fixtures/flow/declare-module/import/actual.js new file mode 100644 index 0000000000..58b3335922 --- /dev/null +++ b/test/fixtures/flow/declare-module/import/actual.js @@ -0,0 +1 @@ +declare module "M" { import type T from "TM"; } diff --git a/test/fixtures/flow/declare-module/import/expected.json b/test/fixtures/flow/declare-module/import/expected.json new file mode 100644 index 0000000000..391e0de595 --- /dev/null +++ b/test/fixtures/flow/declare-module/import/expected.json @@ -0,0 +1,156 @@ +{ + "type": "File", + "start": 0, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 47 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 47 + } + }, + "sourceType": "module", + "body": [ + { + "type": "DeclareModule", + "start": 0, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 47 + } + }, + "id": { + "type": "StringLiteral", + "start": 15, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "extra": { + "rawValue": "M", + "raw": "\"M\"" + }, + "value": "M" + }, + "body": { + "type": "BlockStatement", + "start": 19, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 47 + } + }, + "body": [ + { + "type": "ImportDeclaration", + "start": 21, + "end": 45, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 45 + } + }, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "start": 33, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "local": { + "type": "Identifier", + "start": 33, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 34 + }, + "identifierName": "T" + }, + "name": "T" + } + } + ], + "importKind": "type", + "source": { + "type": "StringLiteral", + "start": 40, + "end": 44, + "loc": { + "start": { + "line": 1, + "column": 40 + }, + "end": { + "line": 1, + "column": 44 + } + }, + "extra": { + "rawValue": "TM", + "raw": "\"TM\"" + }, + "value": "TM" + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/declare-module/invalid-import/actual.js b/test/fixtures/flow/declare-module/invalid-import/actual.js new file mode 100644 index 0000000000..fd091d49f7 --- /dev/null +++ b/test/fixtures/flow/declare-module/invalid-import/actual.js @@ -0,0 +1 @@ +declare module "M" { import T from "TM"; } diff --git a/test/fixtures/flow/declare-module/invalid-import/options.json b/test/fixtures/flow/declare-module/invalid-import/options.json new file mode 100644 index 0000000000..c237bb99a7 --- /dev/null +++ b/test/fixtures/flow/declare-module/invalid-import/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Imports within a `declare module` body must always be `import type` or `import typeof` (1:21)" +}