From 029f6afdeca0f4fed28c07a7ff2fbe7acfcaf79b Mon Sep 17 00:00:00 2001 From: "weiran.zsd" Date: Thu, 14 Mar 2019 21:28:01 +0800 Subject: [PATCH 1/9] Breaking: validate parser options (fixes #384) it will throw an error if any of the conditions is true: + ecmaVersion is invalid + sourceType is invalid + ecmaVersion < 6 & sourceType: "module" --- lib/espree.js | 50 +++++++++++++++++++++++++++++++-------- tests/lib/ecma-version.js | 24 +++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/lib/espree.js b/lib/espree.js index 107affd1..79f29bc1 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 normalizeEcmaVersion(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 normalizeSourceType(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 = normalizeEcmaVersion(options.ecmaVersion); + const sourceType = normalizeSourceType(options.sourceType); + + if (sourceType === "module" && 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 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!/); + }); }); }); From 268b72356b84c21900148e76f180068b6e11b3ae Mon Sep 17 00:00:00 2001 From: "weiran.zsd" Date: Thu, 14 Mar 2019 21:46:50 +0800 Subject: [PATCH 2/9] fix failing tests --- lib/espree.js | 4 ++-- tests/lib/parse.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/espree.js b/lib/espree.js index 79f29bc1..d12c3d3e 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -63,7 +63,7 @@ function normalizeSourceType(sourceType = "script") { * @throws {Error} throw an error if found invalid option. * @returns {Object} normalized options */ -function validate(options) { +function normalizeOptions(options) { const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); const sourceType = normalizeSourceType(options.sourceType); @@ -114,7 +114,7 @@ module.exports = () => Parser => class Espree extends Parser { if (typeof code !== "string" && !(code instanceof String)) { code = String(code); } - const options = validate(opts); + const options = normalizeOptions(opts); const ecmaFeatures = options.ecmaFeatures || {}; const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); diff --git a/tests/lib/parse.js b/tests/lib/parse.js index acae3b99..fe0b73ed 100644 --- a/tests/lib/parse.js +++ b/tests/lib/parse.js @@ -24,7 +24,7 @@ describe("parse()", () => { it("should have correct column number when strict mode error occurs", () => { try { - espree.parse("function fn(a, a) {\n}", { sourceType: "module" }); + espree.parse("function fn(a, a) {\n}", { ecmaVersion: 6, sourceType: "module" }); } catch (err) { assert.strictEqual(err.column, 16); } From fc05f8bf2729da927b9df0c890db1a7be7b64aee Mon Sep 17 00:00:00 2001 From: Kevin Partington Date: Thu, 14 Mar 2019 22:51:38 +0800 Subject: [PATCH 3/9] Update lib/espree.js Co-Authored-By: aladdin-add --- lib/espree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/espree.js b/lib/espree.js index d12c3d3e..668c1693 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -68,7 +68,7 @@ function normalizeOptions(options) { const sourceType = normalizeSourceType(options.sourceType); if (sourceType === "module" && ecmaVersion < 6) { - throw new Error("sourceType 'module' is not supported when ecmaVersion < 6!"); + throw new Error("sourceType 'module' is not supported when ecmaVersion < 6"); } return Object.assign({}, options, { ecmaVersion, sourceType }); } From ac323ffc38b4f2ed00722c059f92066254079792 Mon Sep 17 00:00:00 2001 From: Kevin Partington Date: Thu, 14 Mar 2019 22:53:10 +0800 Subject: [PATCH 4/9] Update tests/lib/ecma-version.js Co-Authored-By: aladdin-add --- tests/lib/ecma-version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index 7b02cd7c..a5fb1754 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -141,7 +141,7 @@ describe("ecmaVersion", () => { }, /Invalid ecmaVersion/); }); - it("Should throw error using invalid year", () => { + it("Should throw error when non-numeric year is provided", () => { assert.throws(() => { espree.parse( "let foo = bar;", { From fd361dff54bae37eb64781393fd58cf97cb88b58 Mon Sep 17 00:00:00 2001 From: "weiran.zsd" Date: Thu, 14 Mar 2019 22:53:53 +0800 Subject: [PATCH 5/9] chore: update test --- tests/lib/ecma-version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index a5fb1754..d21d9908 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -163,7 +163,7 @@ describe("ecmaVersion", () => { sourceType: "module" } ); - }, /sourceType 'module' is not supported when ecmaVersion < 6!/); + }, /sourceType 'module' is not supported when ecmaVersion < 6/); }); }); From 85d1cdf60c8b2b5960eb046f007d103a2fbae9fa Mon Sep 17 00:00:00 2001 From: "weiran.zsd" Date: Thu, 14 Mar 2019 23:10:29 +0800 Subject: [PATCH 6/9] Chore: move some assginment to func normalizeOptions --- lib/espree.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/espree.js b/lib/espree.js index 668c1693..e5c6d60f 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -66,11 +66,13 @@ function normalizeSourceType(sourceType = "script") { function normalizeOptions(options) { const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); const sourceType = normalizeSourceType(options.sourceType); + const ranges = options.range === true; + const locations = options.loc === true; if (sourceType === "module" && ecmaVersion < 6) { - throw new Error("sourceType 'module' is not supported when ecmaVersion < 6"); + throw new Error("sourceType 'module' is not supported when ecmaVersion < 6."); } - return Object.assign({}, options, { ecmaVersion, sourceType }); + return Object.assign({}, options, { ecmaVersion, sourceType, ranges, locations }); } /** @@ -114,10 +116,9 @@ module.exports = () => Parser => class Espree extends Parser { if (typeof code !== "string" && !(code instanceof String)) { code = String(code); } - const options = normalizeOptions(opts); + const options = normalizeOptions(opts); const ecmaFeatures = options.ecmaFeatures || {}; - const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); const tokenTranslator = options.tokens === true ? new TokenTranslator(tokTypes, code) @@ -125,10 +126,12 @@ module.exports = () => Parser => class Espree extends Parser { // Initialize acorn parser. super({ - ecmaVersion, + + // TODO: use {...options} when spread is supported(Node.js >= 8.3.0). + ecmaVersion: options.ecmaVersion, sourceType: options.sourceType, - ranges: options.range === true, - locations: options.loc === true, + ranges: options.ranges, + locations: options.locations, // Truthy value is true for backward compatibility. allowReturnOutsideFunction: Boolean(ecmaFeatures.globalReturn), From 0a58c5d277d5a3a581d72193f18f82457833c53a Mon Sep 17 00:00:00 2001 From: Teddy Katz Date: Fri, 15 Mar 2019 19:13:18 +0800 Subject: [PATCH 7/9] Update lib/espree.js Co-Authored-By: aladdin-add --- lib/espree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/espree.js b/lib/espree.js index e5c6d60f..ba72df73 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -37,7 +37,7 @@ function normalizeEcmaVersion(ecmaVersion = DEFAULT_ECMA_VERSION) { case 10: return version; - default: + // no default } } From fa689da8d69538afac26733c117f7321abf1fcad Mon Sep 17 00:00:00 2001 From: Teddy Katz Date: Fri, 15 Mar 2019 19:14:19 +0800 Subject: [PATCH 8/9] Update lib/espree.js Co-Authored-By: aladdin-add --- lib/espree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/espree.js b/lib/espree.js index ba72df73..6c57a87c 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -70,7 +70,7 @@ function normalizeOptions(options) { const locations = options.loc === true; if (sourceType === "module" && ecmaVersion < 6) { - throw new Error("sourceType 'module' is not supported when ecmaVersion < 6."); + throw new Error("sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options."); } return Object.assign({}, options, { ecmaVersion, sourceType, ranges, locations }); } From e1d09e6e4ddc8dea56c1ed9877f1821f6ad8fa35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 15 Mar 2019 19:26:50 +0800 Subject: [PATCH 9/9] Update ecma-version.js --- tests/lib/ecma-version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index d21d9908..64409853 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -163,7 +163,7 @@ describe("ecmaVersion", () => { sourceType: "module" } ); - }, /sourceType 'module' is not supported when ecmaVersion < 6/); + }, /sourceType 'module' is not supported when ecmaVersion < 2015/); }); });