From fe21e0692718f559111c21a53a273781a2e7ee7e Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 17 Jan 2017 22:04:53 +0100 Subject: [PATCH] keywords are not allowed as local specifier Also fix some error messages to be more specific --- src/parser/expression.js | 9 +++---- src/parser/statement.js | 7 ++++- src/plugins/flow.js | 26 +++++++++---------- .../import-invalid-keyword-flow/actual.js | 1 + .../import-invalid-keyword-flow/options.json | 4 +++ .../actual.js | 1 + .../options.json | 4 +++ .../import-invalid-keyword-typeof/actual.js | 1 + .../options.json | 3 +++ .../modules/import-invalid-keyword/actual.js | 1 + .../import-invalid-keyword/options.json | 3 +++ .../options.json | 4 +-- .../options.json | 4 +-- .../options.json | 4 +-- .../options.json | 2 +- .../options.json | 4 +-- .../invalid-import-type-as/actual.js | 1 + .../invalid-import-type-as/options.json | 3 +++ .../invalid-import-type/actual.js | 1 + .../invalid-import-type/options.json | 3 +++ .../options.json | 2 +- 21 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-flow/actual.js create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-flow/options.json create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/actual.js create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/options.json create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-typeof/actual.js create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword-typeof/options.json create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword/actual.js create mode 100644 test/fixtures/es2015/modules/import-invalid-keyword/options.json create mode 100644 test/fixtures/flow/type-imports/invalid-import-type-as/actual.js create mode 100644 test/fixtures/flow/type-imports/invalid-import-type-as/options.json create mode 100644 test/fixtures/flow/type-imports/invalid-import-type/actual.js create mode 100644 test/fixtures/flow/type-imports/invalid-import-type/options.json diff --git a/src/parser/expression.js b/src/parser/expression.js index 050bc72f42..4937f2b58c 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -1018,14 +1018,13 @@ pp.parseExprListItem = function (allowEmpty, refShorthandDefaultPos) { pp.parseIdentifier = function (liberal) { const node = this.startNode(); + if (!liberal) { + this.checkReservedWord(this.state.value, this.state.start, !!this.state.type.keyword, false); + } if (this.match(tt.name)) { - if (!liberal) { - this.checkReservedWord(this.state.value, this.state.start, false, false); - } - node.name = this.state.value; - } else if (liberal && this.state.type.keyword) { + } else if (this.state.type.keyword) { node.name = this.state.type.keyword; } else { this.unexpected(); diff --git a/src/parser/statement.js b/src/parser/statement.js index 821021e57e..5df52b3037 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -1075,7 +1075,12 @@ pp.parseImportSpecifiers = function (node) { pp.parseImportSpecifier = function (node) { const specifier = this.startNode(); specifier.imported = this.parseIdentifier(true); - specifier.local = this.eatContextual("as") ? this.parseIdentifier() : specifier.imported.__clone(); + if (this.eatContextual("as")) { + specifier.local = this.parseIdentifier(); + } else { + this.checkReservedWord(specifier.imported.name, specifier.start, true, true); + specifier.local = specifier.imported.__clone(); + } this.checkLVal(specifier.local, true, undefined, "import specifier"); node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); }; diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 8927bed198..9751347cc0 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1221,9 +1221,10 @@ export default function (instance) { specifierTypeKind = "typeof"; } + let isBinding = false; if (this.isContextual("as")) { const as_ident = this.parseIdentifier(true); - if (specifierTypeKind !== null && !this.match(tt.name)) { + if (specifierTypeKind !== null && !this.match(tt.name) && !this.state.type.keyword) { // `import {type as ,` or `import {type as }` specifier.imported = as_ident; specifier.importKind = specifierTypeKind; @@ -1232,23 +1233,20 @@ export default function (instance) { // `import {type as foo` specifier.imported = firstIdent; specifier.importKind = null; - specifier.local = this.parseIdentifier(false); + specifier.local = this.parseIdentifier(); } - } else if (specifierTypeKind !== null && this.match(tt.name)) { + } else if (specifierTypeKind !== null && (this.match(tt.name) || this.state.type.keyword)) { // `import {type foo` specifier.imported = this.parseIdentifier(true); specifier.importKind = specifierTypeKind; - specifier.local = - this.eatContextual("as") - ? this.parseIdentifier(false) - : specifier.imported.__clone(); - } else { - if (firstIdent.name === "typeof") { - this.unexpected( - firstIdentLoc, - "Cannot import a variable named `typeof`" - ); + if (this.eatContextual("as")) { + specifier.local = this.parseIdentifier(); + } else { + isBinding = true; + specifier.local = specifier.imported.__clone(); } + } else { + isBinding = true; specifier.imported = firstIdent; specifier.importKind = null; specifier.local = specifier.imported.__clone(); @@ -1261,6 +1259,8 @@ export default function (instance) { this.raise(firstIdentLoc, "`The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements`"); } + if (isBinding) this.checkReservedWord(specifier.local.name, specifier.start, true, true); + this.checkLVal(specifier.local, true, undefined, "import specifier"); node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); }; diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-flow/actual.js b/test/fixtures/es2015/modules/import-invalid-keyword-flow/actual.js new file mode 100644 index 0000000000..e086d4c8c0 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-flow/actual.js @@ -0,0 +1 @@ +import { default } from "foo"; diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-flow/options.json b/test/fixtures/es2015/modules/import-invalid-keyword-flow/options.json new file mode 100644 index 0000000000..243fc2686d --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-flow/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["flow"], + "throws": "default is a reserved word (1:9)" +} diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/actual.js b/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/actual.js new file mode 100644 index 0000000000..9b90a09d17 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/actual.js @@ -0,0 +1 @@ +import { typeof } from "foo"; diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/options.json b/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/options.json new file mode 100644 index 0000000000..fa0493b7e1 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-typeof-flow/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["flow"], + "throws": "typeof is a reserved word (1:9)" +} diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-typeof/actual.js b/test/fixtures/es2015/modules/import-invalid-keyword-typeof/actual.js new file mode 100644 index 0000000000..9b90a09d17 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-typeof/actual.js @@ -0,0 +1 @@ +import { typeof } from "foo"; diff --git a/test/fixtures/es2015/modules/import-invalid-keyword-typeof/options.json b/test/fixtures/es2015/modules/import-invalid-keyword-typeof/options.json new file mode 100644 index 0000000000..0f27b53e91 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword-typeof/options.json @@ -0,0 +1,3 @@ +{ + "throws": "typeof is a reserved word (1:9)" +} diff --git a/test/fixtures/es2015/modules/import-invalid-keyword/actual.js b/test/fixtures/es2015/modules/import-invalid-keyword/actual.js new file mode 100644 index 0000000000..a67e334a86 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword/actual.js @@ -0,0 +1 @@ +import { debugger } from "foo"; diff --git a/test/fixtures/es2015/modules/import-invalid-keyword/options.json b/test/fixtures/es2015/modules/import-invalid-keyword/options.json new file mode 100644 index 0000000000..96dff35646 --- /dev/null +++ b/test/fixtures/es2015/modules/import-invalid-keyword/options.json @@ -0,0 +1,3 @@ +{ + "throws": "debugger is a reserved word (1:9)" +} diff --git a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-declaration/options.json b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-declaration/options.json index 00b62a33f8..f0d1a6cf1a 100644 --- a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-declaration/options.json +++ b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-declaration/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:26)" -} \ No newline at end of file + "throws": "yield is a reserved word (1:26)" +} diff --git a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-function-declaration/options.json b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-function-declaration/options.json index b242442b4c..4e58c050ba 100644 --- a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-function-declaration/options.json +++ b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-function-declaration/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:25)" -} \ No newline at end of file + "throws": "yield is a reserved word (1:25)" +} diff --git a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-strict-function-expression/options.json b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-strict-function-expression/options.json index d34690fa60..55db1979e6 100644 --- a/test/fixtures/esprima/es2015-yield/invalid-yield-generator-strict-function-expression/options.json +++ b/test/fixtures/esprima/es2015-yield/invalid-yield-generator-strict-function-expression/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:46)" -} \ No newline at end of file + "throws": "yield is a reserved word (1:46)" +} diff --git a/test/fixtures/esprima/es2015-yield/invalid-yield-strict-identifier/options.json b/test/fixtures/esprima/es2015-yield/invalid-yield-strict-identifier/options.json index 6079f138a6..36e90ef404 100644 --- a/test/fixtures/esprima/es2015-yield/invalid-yield-strict-identifier/options.json +++ b/test/fixtures/esprima/es2015-yield/invalid-yield-strict-identifier/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:29)" + "throws": "yield is a reserved word (1:29)" } diff --git a/test/fixtures/esprima/es2015-yield/invalid-yield-strict-rest-parameter/options.json b/test/fixtures/esprima/es2015-yield/invalid-yield-strict-rest-parameter/options.json index f55830c1c3..5d2e075e37 100644 --- a/test/fixtures/esprima/es2015-yield/invalid-yield-strict-rest-parameter/options.json +++ b/test/fixtures/esprima/es2015-yield/invalid-yield-strict-rest-parameter/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:28)" -} \ No newline at end of file + "throws": "yield is a reserved word (1:28)" +} diff --git a/test/fixtures/flow/type-imports/invalid-import-type-as/actual.js b/test/fixtures/flow/type-imports/invalid-import-type-as/actual.js new file mode 100644 index 0000000000..4cd7177a5c --- /dev/null +++ b/test/fixtures/flow/type-imports/invalid-import-type-as/actual.js @@ -0,0 +1 @@ +import { type as debugger } from "foo"; diff --git a/test/fixtures/flow/type-imports/invalid-import-type-as/options.json b/test/fixtures/flow/type-imports/invalid-import-type-as/options.json new file mode 100644 index 0000000000..011c7d25da --- /dev/null +++ b/test/fixtures/flow/type-imports/invalid-import-type-as/options.json @@ -0,0 +1,3 @@ +{ + "throws": "debugger is a reserved word (1:17)" +} diff --git a/test/fixtures/flow/type-imports/invalid-import-type/actual.js b/test/fixtures/flow/type-imports/invalid-import-type/actual.js new file mode 100644 index 0000000000..b8ee08bd2d --- /dev/null +++ b/test/fixtures/flow/type-imports/invalid-import-type/actual.js @@ -0,0 +1 @@ +import { type debugger } from "foo"; diff --git a/test/fixtures/flow/type-imports/invalid-import-type/options.json b/test/fixtures/flow/type-imports/invalid-import-type/options.json new file mode 100644 index 0000000000..96dff35646 --- /dev/null +++ b/test/fixtures/flow/type-imports/invalid-import-type/options.json @@ -0,0 +1,3 @@ +{ + "throws": "debugger is a reserved word (1:9)" +} diff --git a/test/fixtures/flow/type-parameter-declaration/reserved-word-class-name-failure/options.json b/test/fixtures/flow/type-parameter-declaration/reserved-word-class-name-failure/options.json index e8ad1c3a24..e8aeb07ed7 100644 --- a/test/fixtures/flow/type-parameter-declaration/reserved-word-class-name-failure/options.json +++ b/test/fixtures/flow/type-parameter-declaration/reserved-word-class-name-failure/options.json @@ -1,4 +1,4 @@ { - "throws": "Unexpected token (1:14)", + "throws": "delete is a reserved word (1:14)", "plugins": ["flow", "jsx"] }