diff --git a/README.md b/README.md index b8bad72b..d68eb015 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ const ast = espree.parse(code); `parse` parses the given code and returns a abstract syntax tree (AST). It takes two parameters. -- `code` [string]() - the code which needs to be parsed. +- `code` [string]() - the code which needs to be parsed. - `options (Optional)` [Object]() - read more about this [here](#options). ```js @@ -81,7 +81,7 @@ Node { `tokenize` returns the tokens of a given code. It takes two parameters. -- `code` [string]() - the code which needs to be parsed. +- `code` [string]() - the code which needs to be parsed. - `options (Optional)` [Object]() - read more about this [here](#options). Even if `options` is empty or undefined or `options.tokens` is `false`, it assigns it to `true` in order to get the `tokens` array @@ -124,7 +124,7 @@ Returns the latest ECMAScript supported by `espree` Returns an array of all supported ECMAScript versions -## Options +## Options ```js const options = { @@ -143,7 +143,9 @@ const options = { // Set to 3, 5 (the default), 6, 7, 8, 9, 10, 11, or 12 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. - ecmaVersion: 5, + ecmaVersion: 3, + + allowReserved: true, // only allowed when ecmaVersion is 3 // specify which type of script you're parsing ("script", "module", or "commonjs") sourceType: "script", diff --git a/lib/options.js b/lib/options.js index 02c1a750..87739699 100644 --- a/lib/options.js +++ b/lib/options.js @@ -92,7 +92,16 @@ export function normalizeOptions(options) { const sourceType = normalizeSourceType(options.sourceType); const ranges = options.range === true; const locations = options.loc === true; - const allowReserved = ecmaVersion === 3 ? "never" : false; + + if (ecmaVersion !== 3 && options.allowReserved) { + + // a value of `false` is intentionally allowed here, so a shared config can overwrite it when needed + throw new Error("`allowReserved` is only supported when ecmaVersion is 3"); + } + if (typeof options.allowReserved !== "undefined" && typeof options.allowReserved !== "boolean") { + throw new Error("`allowReserved`, when present, must be `true` or `false`"); + } + const allowReserved = ecmaVersion === 3 ? (options.allowReserved || "never") : false; const ecmaFeatures = options.ecmaFeatures || {}; const allowReturnOutsideFunction = options.sourceType === "commonjs" || Boolean(ecmaFeatures.globalReturn); diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index 05d76e0f..6d81b5cd 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -196,6 +196,72 @@ describe("ecmaVersion", () => { }, /'char' is reserved/u); }); + it("Should throw error when using ES3, allowReserved: false, and reserved words", () => { + assert.throws(() => { + espree.parse( + "var char = 'c'", { + ecmaVersion: 3, + allowReserved: false + } + ); + }, /'char' is reserved/u); + }); + + it("Should not throw error when using ES3, allowReserved: true, and reserved words", () => { + assert.doesNotThrow(() => { + espree.parse( + "var char = 'c'", { + ecmaVersion: 3, + allowReserved: true + } + ); + }); + }); + + it("Should not throw error when using ES3, allowReserved: true, and reserved words in object literals", () => { + assert.doesNotThrow(() => { + espree.parse( + "var x = { char: 'c' }", { + ecmaVersion: 3, + allowReserved: true + } + ); + }); + }); + + it("Should throw error when using ES5, allowReserved: true", () => { + assert.throws(() => { + espree.parse( + "var x = { char: 'c' }", { + ecmaVersion: 5, + allowReserved: true + } + ); + }, /`allowReserved` is only supported when ecmaVersion is 3/u); + }); + + it("Should throw error when using ES3, allowReserved: non-boolean", () => { + assert.throws(() => { + espree.parse( + "var x = { char: 'c' }", { + ecmaVersion: 3, + allowReserved: "true" + } + ); + }, /`allowReserved`, when present, must be `true` or `false`/u); + }); + + it("Should not throw error when using ES5, allowReserved: false, and ES3 reserved words in object literals", () => { + assert.doesNotThrow(() => { + espree.parse( + "var x = { char: 'c' }", { + ecmaVersion: 5, + allowReserved: false + } + ); + }); + }); + it("Should throw error when using module in pre-ES6", () => { assert.throws(() => { espree.parse(