From ca6ce295fb4af9dce0c97ab55a92f70867cd9cba Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Fri, 3 Dec 2021 14:48:28 +0100 Subject: [PATCH 1/2] feat: add `allowReserved` parser option Fixes #15327 --- .../configuring/language-options.md | 1 + lib/shared/types.js | 1 + package.json | 2 +- tests/lib/linter/linter.js | 76 +++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/configuring/language-options.md b/docs/user-guide/configuring/language-options.md index 37fbbe6e3d1..d44959df2bb 100644 --- a/docs/user-guide/configuring/language-options.md +++ b/docs/user-guide/configuring/language-options.md @@ -187,6 +187,7 @@ Parser options are set in your `.eslintrc.*` file by using the `parserOptions` p * `ecmaVersion` - set to 3, 5 (default), 6, 7, 8, 9, 10, 11, 12, or 13 to specify the version of ECMAScript syntax you want to use. You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), 2018 (same as 9), 2019 (same as 10), 2020 (same as 11), 2021 (same as 12), or 2022 (same as 13) to use the year-based naming. You can also set "latest" to use the most recently supported version. * `sourceType` - set to `"script"` (default) or `"module"` if your code is in ECMAScript modules. +* `allowReserved` - allow the use of reserved words as identifiers (if `ecmaVersion` is 3). * `ecmaFeatures` - an object indicating which additional language features you'd like to use: * `globalReturn` - allow `return` statements in the global scope * `impliedStrict` - enable global [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) (if `ecmaVersion` is 5 or greater) diff --git a/lib/shared/types.js b/lib/shared/types.js index c497f783be5..8dfb022ab9b 100644 --- a/lib/shared/types.js +++ b/lib/shared/types.js @@ -23,6 +23,7 @@ module.exports = {}; * @property {EcmaFeatures} [ecmaFeatures] The optional features. * @property {3|5|6|7|8|9|10|11|12|13|2015|2016|2017|2018|2019|2020|2021|2022} [ecmaVersion] The ECMAScript version (or revision number). * @property {"script"|"module"} [sourceType] The source code type. + * @property {boolean} [allowReserved] Allowing the use of reserved words as identifiers in ES3. */ /** diff --git a/package.json b/package.json index 6fc8d28770e..c5efd8a8f1b 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", + "espree": "github:eslint/espree#prepare-v9.2.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js index 24dc4de43ce..4f4e73f0ee4 100644 --- a/tests/lib/linter/linter.js +++ b/tests/lib/linter/linter.js @@ -4358,6 +4358,82 @@ var a = "test2"; assert.strictEqual(messages.length, 0); }); + it("should not allow the use of reserved words as variable names in ES3", () => { + const code = "var char;"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion: 3 } }, filename); + + assert.strictEqual(messages.length, 1); + assert.strictEqual(messages[0].severity, 2); + assert.isTrue(messages[0].fatal); + assert.match(messages[0].message, /^Parsing error:.*'char'/u); + }); + + it("should not allow the use of reserved words as property names in member expressions in ES3", () => { + const code = "obj.char;"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion: 3 } }, filename); + + assert.strictEqual(messages.length, 1); + assert.strictEqual(messages[0].severity, 2); + assert.isTrue(messages[0].fatal); + assert.match(messages[0].message, /^Parsing error:.*'char'/u); + }); + + it("should not allow the use of reserved words as property names in object literals in ES3", () => { + const code = "var obj = { char: 1 };"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion: 3 } }, filename); + + assert.strictEqual(messages.length, 1); + assert.strictEqual(messages[0].severity, 2); + assert.isTrue(messages[0].fatal); + assert.match(messages[0].message, /^Parsing error:.*'char'/u); + }); + + it("should allow the use of reserved words as variable and property names in ES3 when allowReserved is true", () => { + const code = "var char; obj.char; var obj = { char: 1 };"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion: 3, allowReserved: true } }, filename); + + assert.strictEqual(messages.length, 0); + }); + + it("should not allow the use of reserved words as variable names in ES > 3", () => { + const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)]; + + ecmaVersions.forEach(ecmaVersion => { + const code = "var enum;"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion } }, filename); + + assert.strictEqual(messages.length, 1); + assert.strictEqual(messages[0].severity, 2); + assert.isTrue(messages[0].fatal); + assert.match(messages[0].message, /^Parsing error:.*'enum'/u); + }); + }); + + it("should allow the use of reserved words as property names in ES > 3", () => { + const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)]; + + ecmaVersions.forEach(ecmaVersion => { + const code = "obj.enum; obj.function; var obj = { enum: 1, function: 2 };"; + const messages = linter.verify(code, { parserOptions: { ecmaVersion } }, filename); + + assert.strictEqual(messages.length, 0); + }); + }); + + it("should not allow `allowReserved: true` in ES > 3", () => { + const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)]; + + ecmaVersions.forEach(ecmaVersion => { + const code = ""; + const messages = linter.verify(code, { parserOptions: { ecmaVersion, allowReserved: true } }, filename); + + assert.strictEqual(messages.length, 1); + assert.strictEqual(messages[0].severity, 2); + assert.isTrue(messages[0].fatal); + assert.match(messages[0].message, /^Parsing error:.*allowReserved/u); + }); + }); + it("should be able to use es6 features if there is a comment which has \"eslint-env es6\"", () => { const code = [ "/* eslint-env es6 */", From f46a4e7cc17e4981d5e9ad7d7c8e0e35f60126ab Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Sat, 4 Dec 2021 01:53:38 +0100 Subject: [PATCH 2/2] update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c5efd8a8f1b..7daf3eb6110 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.1.0", - "espree": "github:eslint/espree#prepare-v9.2.0", + "espree": "^9.2.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3",