diff --git a/lib/espree.js b/lib/espree.js index 107affd1..770d9105 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -10,12 +10,14 @@ const STATE = Symbol("espree's internal state"); const ESPRIMA_FINISH_NODE = Symbol("espree's esprimaFinishNode"); const tokTypes = Object.assign({}, acorn.tokTypes, jsx.tokTypes); + /** * Normalize ECMAScript version from the initial config * @param {number} 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) { +function validateEcmaVersion(ecmaVersion = DEFAULT_ECMA_VERSION) { if (typeof ecmaVersion === "number") { let version = ecmaVersion; @@ -36,11 +38,39 @@ function normalizeEcmaVersion(ecmaVersion) { return version; default: - throw new Error("Invalid ecmaVersion."); } - } else { - return DEFAULT_ECMA_VERSION; } + + throw new Error("Invalid ecmaVersion."); +} + +/** + * Normalize sourceType from the initial config + * @param {string} sourceType to normalize + * @throws {Error} throw an error if sourceType is invalid + * @returns {string} normalized sourceType + */ +function validateSourceType(sourceType = "script") { + if (sourceType === "script" || sourceType === "module") { + return sourceType; + } + throw new Error("Invalid sourceType."); +} + +/** + * Normalize parserOptions + * @param {Object} options the parser options to normalize + * @throws {Error} throw an error if found invalid option. + * @returns {Object} normalized options + */ +function validate(options) { + const ecmaVersion = validateEcmaVersion(options.ecmaVersion); + const sourceType = validateSourceType(options.sourceType); + + if (options.sourceType === "module" && options.ecmaVersion < 6) { + throw new Error("sourceType 'module' is not supported when ecmaVersion < 6!"); + } + return Object.assign({}, options, { ecmaVersion, sourceType }); } /** @@ -77,17 +107,17 @@ function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, } module.exports = () => Parser => class Espree extends Parser { - constructor(options, code) { - if (typeof options !== "object" || options === null) { - options = {}; + constructor(opts, code) { + if (typeof opts !== "object" || opts === null) { + opts = {}; } if (typeof code !== "string" && !(code instanceof String)) { code = String(code); } + const options = validate(opts); const ecmaFeatures = options.ecmaFeatures || {}; - const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); - const isModule = options.sourceType === "module"; + const ecmaVersion = validateEcmaVersion(options.ecmaVersion); const tokenTranslator = options.tokens === true ? new TokenTranslator(tokTypes, code) @@ -95,8 +125,8 @@ module.exports = () => Parser => class Espree extends Parser { // Initialize acorn parser. super({ - ecmaVersion: isModule ? Math.max(6, ecmaVersion) : ecmaVersion, - sourceType: isModule ? "module" : "script", + ecmaVersion, + sourceType: options.sourceType, ranges: options.range === true, locations: options.loc === true, diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index bd533d4e..7b02cd7c 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -141,6 +141,30 @@ describe("ecmaVersion", () => { }, /Invalid ecmaVersion/); }); + it("Should throw error using invalid year", () => { + assert.throws(() => { + espree.parse( + "let foo = bar;", { + ecmaVersion: "2015", + comment: true, + tokens: true, + range: true, + loc: true + } + ); + }, /Invalid ecmaVersion/); + }); + + it("Should throw error when using module in pre-ES6", () => { + assert.throws(() => { + espree.parse( + "let foo = bar;", { + ecmaVersion: 5, + sourceType: "module" + } + ); + }, /sourceType 'module' is not supported when ecmaVersion < 6!/); + }); }); });