diff --git a/README.md b/README.md index 0c445c02..f59c074c 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,9 @@ const options = { // create a top-level tokens array containing all tokens tokens: false, - // Set to 3, 5 (default), 6, 7, 8, 9, 10, 11, or 12 to specify the version of ECMAScript syntax you want to use. + // Set to 3, 5, 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), or 2021 (same as 12) to use the year-based naming. + // You can also set "latest" (the default) to use the most recently supported version. ecmaVersion: 5, // specify which type of script you're parsing ("script" or "module") diff --git a/lib/options.js b/lib/options.js index 855d5187..be07f914 100644 --- a/lib/options.js +++ b/lib/options.js @@ -7,7 +7,6 @@ // Helpers //------------------------------------------------------------------------------ -const DEFAULT_ECMA_VERSION = 5; const SUPPORTED_VERSIONS = [ 3, 5, @@ -20,18 +19,35 @@ const SUPPORTED_VERSIONS = [ 12 ]; +/** + * Get the latest ECMAScript version supported by Espree. + * @returns {number} The latest ECMAScript version. + */ +export function getLatestEcmaVersion() { + return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1]; +} + +/** + * Get the list of ECMAScript versions supported by Espree. + * @returns {number[]} An array containing the supported ECMAScript versions. + */ +export function getSupportedEcmaVersions() { + return [...SUPPORTED_VERSIONS]; +} + /** * Normalize ECMAScript version from the initial config - * @param {number} ecmaVersion ECMAScript version from the initial config + * @param {(number|"latest")} ecmaVersion ECMAScript version from the initial config * @throws {Error} throws an error if the ecmaVersion is invalid. * @returns {number} normalized ECMAScript version */ -function normalizeEcmaVersion(ecmaVersion = DEFAULT_ECMA_VERSION) { - if (typeof ecmaVersion !== "number") { - throw new Error(`ecmaVersion must be a number. Received value of type ${typeof ecmaVersion} instead.`); - } +function normalizeEcmaVersion(ecmaVersion = getLatestEcmaVersion()) { - let version = ecmaVersion; + let version = ecmaVersion === "latest" ? getLatestEcmaVersion() : ecmaVersion; + + if (typeof version !== "number") { + throw new Error(`ecmaVersion must be a number or "latest". Received value of type ${typeof ecmaVersion} instead.`); + } // Calculate ECMAScript edition number from official year version starting with // ES2015, which corresponds with ES6 (or a difference of 2009). @@ -76,19 +92,3 @@ export function normalizeOptions(options) { } return Object.assign({}, options, { ecmaVersion, sourceType, ranges, locations }); } - -/** - * Get the latest ECMAScript version supported by Espree. - * @returns {number} The latest ECMAScript version. - */ -export function getLatestEcmaVersion() { - return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1]; -} - -/** - * Get the list of ECMAScript versions supported by Espree. - * @returns {number[]} An array containing the supported ECMAScript versions. - */ -export function getSupportedEcmaVersions() { - return [...SUPPORTED_VERSIONS]; -} diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index 9a264811..5d336fdb 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -173,7 +173,7 @@ describe("ecmaVersion", () => { loc: true } ); - }, /ecmaVersion must be a number. Received value of type string instead/u); + }, /ecmaVersion must be a number or "latest". Received value of type string instead/u); }); it("Should throw error when using module in pre-ES6", () => { @@ -186,6 +186,41 @@ describe("ecmaVersion", () => { ); }, /sourceType 'module' is not supported when ecmaVersion < 2015/u); }); + + it("Should allow 'latest' as value", () => { + const expected = espree.parse( + "let foo = bar;", { + ecmaVersion: espree.latestEcmaVersion, + sourceType: "module" + } + ); + + const actual = espree.parse( + "let foo = bar;", { + ecmaVersion: "latest", + sourceType: "module" + } + ); + + assert.deepStrictEqual(actual, expected); + }); + + it("Should use the latestEcmaVersion as the default for ecmaVersion", () => { + const expected = espree.parse( + "let foo = bar;", { + ecmaVersion: espree.latestEcmaVersion, + sourceType: "module" + } + ); + + const actual = espree.parse( + "let foo = bar;", { + sourceType: "module" + } + ); + + assert.deepStrictEqual(actual, expected); + }); }); }); diff --git a/tests/lib/libraries.js b/tests/lib/libraries.js index b69105fb..6903853b 100644 --- a/tests/lib/libraries.js +++ b/tests/lib/libraries.js @@ -37,8 +37,8 @@ describe("Libraries", () => { it("should produce correct AST when parsed", () => { const output = shelljs.cat(`${filename}.result.json`); const input = shelljs.cat(filename); - const result = JSON.stringify(tester.getRaw(espree.parse(input, { + ecmaVersion: 5, loc: true, range: true, tokens: true diff --git a/tests/lib/options.js b/tests/lib/options.js index 28d23b03..61c9ac85 100644 --- a/tests/lib/options.js +++ b/tests/lib/options.js @@ -8,7 +8,7 @@ //------------------------------------------------------------------------------ import assert from "assert"; -import { normalizeOptions } from "../../lib/options.js"; +import { normalizeOptions, getLatestEcmaVersion } from "../../lib/options.js"; //------------------------------------------------------------------------------ @@ -16,12 +16,20 @@ import { normalizeOptions } from "../../lib/options.js"; //------------------------------------------------------------------------------ describe("normalizeOptions", () => { - it("should set ecmaVersion to 5 if it wasn't specified", () => { + it("should set ecmaVersion to latestEcmaVersion if it wasn't specified", () => { const option = {}; const output = normalizeOptions(option); - assert.strictEqual(output.ecmaVersion, 5); + assert.strictEqual(output.ecmaVersion, getLatestEcmaVersion()); + }); + + it("should set ecmaVersion to latestEcmaVersion if ecmaVersion: latest is passed", () => { + const output = normalizeOptions({ + ecmaVersion: "latest" + }); + + assert.strictEqual(output.ecmaVersion, getLatestEcmaVersion()); }); it("should throw error for sourceType module and ecmaVersion < 6", () => { diff --git a/tests/lib/parse.js b/tests/lib/parse.js index 79526d7b..7df027f2 100644 --- a/tests/lib/parse.js +++ b/tests/lib/parse.js @@ -23,15 +23,10 @@ describe("parse()", () => { describe("ecmaVersion", () => { - it("should be 5 if not specified", () => { + it("should be latestEcmaVersion if not specified", () => { - // `ecmaVersion: 3` would throw on getters/setters - espree.parse("var foo = { get bar() {} }"); - - // needs `ecmaVersion: 6` or higher - assert.throws(() => { - espree.parse("let foo"); - }); + // `ecmaVersion: 5` would throw on async + espree.parse("let foo = { async bar() {} }"); }); }); @@ -54,14 +49,14 @@ describe("parse()", () => { it("should throw an error when using the y regex flag", () => { assert.throws(() => { - espree.parse("/./y"); + espree.parse("/./y", { ecmaVersion: 5 }); }); }); it("should throw an error when using the u regex flag", () => { assert.throws(() => { - espree.parse("/./u"); + espree.parse("/./u", { ecmaVersion: 5 }); }); }); diff --git a/tests/lib/tokenize.js b/tests/lib/tokenize.js index 5d661a70..e4539c8b 100644 --- a/tests/lib/tokenize.js +++ b/tests/lib/tokenize.js @@ -30,14 +30,10 @@ import tildeOperatorTokens from "../fixtures/tokenize/tilde-operator.tokens.js"; describe("tokenize()", () => { - it("should have `ecmaVersion: 5` as default", () => { - - // FIXME: is there a way to test that it isn't `ecmaVersion: 3`? + it("should have latestEcmaVersion as default", () => { // needs `ecmaVersion: 6` or higher - assert.throws(() => { - espree.tokenize("`template`"); - }); + espree.tokenize("`template`"); }); it("should produce tokens when using let", () => {