Skip to content

Commit b068cea

Browse files
nzakasbtmills
andauthored
Breaking: Implement 'ecmaVersion: latest' (fixes #495) (#499)
* Breaking: Implement 'ecmaVersion: latest' (fixes #495) * Update lib/options.js Co-authored-by: Brandon Mills <[email protected]> * Add extra test Co-authored-by: Brandon Mills <[email protected]>
1 parent 8294427 commit b068cea

File tree

7 files changed

+80
-45
lines changed

7 files changed

+80
-45
lines changed

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,9 @@ const options = {
140140
// create a top-level tokens array containing all tokens
141141
tokens: false,
142142

143-
// Set to 3, 5 (default), 6, 7, 8, 9, 10, 11, or 12 to specify the version of ECMAScript syntax you want to use.
143+
// Set to 3, 5, 6, 7, 8, 9, 10, 11, or 12 to specify the version of ECMAScript syntax you want to use.
144144
// 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.
145+
// You can also set "latest" (the default) to use the most recently supported version.
145146
ecmaVersion: 5,
146147

147148
// specify which type of script you're parsing ("script" or "module")

Diff for: lib/options.js

+23-23
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// Helpers
88
//------------------------------------------------------------------------------
99

10-
const DEFAULT_ECMA_VERSION = 5;
1110
const SUPPORTED_VERSIONS = [
1211
3,
1312
5,
@@ -20,18 +19,35 @@ const SUPPORTED_VERSIONS = [
2019
12
2120
];
2221

22+
/**
23+
* Get the latest ECMAScript version supported by Espree.
24+
* @returns {number} The latest ECMAScript version.
25+
*/
26+
export function getLatestEcmaVersion() {
27+
return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1];
28+
}
29+
30+
/**
31+
* Get the list of ECMAScript versions supported by Espree.
32+
* @returns {number[]} An array containing the supported ECMAScript versions.
33+
*/
34+
export function getSupportedEcmaVersions() {
35+
return [...SUPPORTED_VERSIONS];
36+
}
37+
2338
/**
2439
* Normalize ECMAScript version from the initial config
25-
* @param {number} ecmaVersion ECMAScript version from the initial config
40+
* @param {(number|"latest")} ecmaVersion ECMAScript version from the initial config
2641
* @throws {Error} throws an error if the ecmaVersion is invalid.
2742
* @returns {number} normalized ECMAScript version
2843
*/
29-
function normalizeEcmaVersion(ecmaVersion = DEFAULT_ECMA_VERSION) {
30-
if (typeof ecmaVersion !== "number") {
31-
throw new Error(`ecmaVersion must be a number. Received value of type ${typeof ecmaVersion} instead.`);
32-
}
44+
function normalizeEcmaVersion(ecmaVersion = getLatestEcmaVersion()) {
3345

34-
let version = ecmaVersion;
46+
let version = ecmaVersion === "latest" ? getLatestEcmaVersion() : ecmaVersion;
47+
48+
if (typeof version !== "number") {
49+
throw new Error(`ecmaVersion must be a number or "latest". Received value of type ${typeof ecmaVersion} instead.`);
50+
}
3551

3652
// Calculate ECMAScript edition number from official year version starting with
3753
// ES2015, which corresponds with ES6 (or a difference of 2009).
@@ -76,19 +92,3 @@ export function normalizeOptions(options) {
7692
}
7793
return Object.assign({}, options, { ecmaVersion, sourceType, ranges, locations });
7894
}
79-
80-
/**
81-
* Get the latest ECMAScript version supported by Espree.
82-
* @returns {number} The latest ECMAScript version.
83-
*/
84-
export function getLatestEcmaVersion() {
85-
return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1];
86-
}
87-
88-
/**
89-
* Get the list of ECMAScript versions supported by Espree.
90-
* @returns {number[]} An array containing the supported ECMAScript versions.
91-
*/
92-
export function getSupportedEcmaVersions() {
93-
return [...SUPPORTED_VERSIONS];
94-
}

Diff for: tests/lib/ecma-version.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ describe("ecmaVersion", () => {
173173
loc: true
174174
}
175175
);
176-
}, /ecmaVersion must be a number. Received value of type string instead/u);
176+
}, /ecmaVersion must be a number or "latest". Received value of type string instead/u);
177177
});
178178

179179
it("Should throw error when using module in pre-ES6", () => {
@@ -186,6 +186,41 @@ describe("ecmaVersion", () => {
186186
);
187187
}, /sourceType 'module' is not supported when ecmaVersion < 2015/u);
188188
});
189+
190+
it("Should allow 'latest' as value", () => {
191+
const expected = espree.parse(
192+
"let foo = bar;", {
193+
ecmaVersion: espree.latestEcmaVersion,
194+
sourceType: "module"
195+
}
196+
);
197+
198+
const actual = espree.parse(
199+
"let foo = bar;", {
200+
ecmaVersion: "latest",
201+
sourceType: "module"
202+
}
203+
);
204+
205+
assert.deepStrictEqual(actual, expected);
206+
});
207+
208+
it("Should use the latestEcmaVersion as the default for ecmaVersion", () => {
209+
const expected = espree.parse(
210+
"let foo = bar;", {
211+
ecmaVersion: espree.latestEcmaVersion,
212+
sourceType: "module"
213+
}
214+
);
215+
216+
const actual = espree.parse(
217+
"let foo = bar;", {
218+
sourceType: "module"
219+
}
220+
);
221+
222+
assert.deepStrictEqual(actual, expected);
223+
});
189224
});
190225

191226
});

Diff for: tests/lib/libraries.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ describe("Libraries", () => {
3737
it("should produce correct AST when parsed", () => {
3838
const output = shelljs.cat(`${filename}.result.json`);
3939
const input = shelljs.cat(filename);
40-
4140
const result = JSON.stringify(tester.getRaw(espree.parse(input, {
41+
ecmaVersion: 5,
4242
loc: true,
4343
range: true,
4444
tokens: true

Diff for: tests/lib/options.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,28 @@
88
//------------------------------------------------------------------------------
99

1010
import assert from "assert";
11-
import { normalizeOptions } from "../../lib/options.js";
11+
import { normalizeOptions, getLatestEcmaVersion } from "../../lib/options.js";
1212

1313

1414
//------------------------------------------------------------------------------
1515
// Tests
1616
//------------------------------------------------------------------------------
1717

1818
describe("normalizeOptions", () => {
19-
it("should set ecmaVersion to 5 if it wasn't specified", () => {
19+
it("should set ecmaVersion to latestEcmaVersion if it wasn't specified", () => {
2020
const option = {};
2121

2222
const output = normalizeOptions(option);
2323

24-
assert.strictEqual(output.ecmaVersion, 5);
24+
assert.strictEqual(output.ecmaVersion, getLatestEcmaVersion());
25+
});
26+
27+
it("should set ecmaVersion to latestEcmaVersion if ecmaVersion: latest is passed", () => {
28+
const output = normalizeOptions({
29+
ecmaVersion: "latest"
30+
});
31+
32+
assert.strictEqual(output.ecmaVersion, getLatestEcmaVersion());
2533
});
2634

2735
it("should throw error for sourceType module and ecmaVersion < 6", () => {

Diff for: tests/lib/parse.js

+5-10
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,10 @@ describe("parse()", () => {
2323

2424
describe("ecmaVersion", () => {
2525

26-
it("should be 5 if not specified", () => {
26+
it("should be latestEcmaVersion if not specified", () => {
2727

28-
// `ecmaVersion: 3` would throw on getters/setters
29-
espree.parse("var foo = { get bar() {} }");
30-
31-
// needs `ecmaVersion: 6` or higher
32-
assert.throws(() => {
33-
espree.parse("let foo");
34-
});
28+
// `ecmaVersion: 5` would throw on async
29+
espree.parse("let foo = { async bar() {} }");
3530
});
3631

3732
});
@@ -54,14 +49,14 @@ describe("parse()", () => {
5449
it("should throw an error when using the y regex flag", () => {
5550

5651
assert.throws(() => {
57-
espree.parse("/./y");
52+
espree.parse("/./y", { ecmaVersion: 5 });
5853
});
5954
});
6055

6156
it("should throw an error when using the u regex flag", () => {
6257

6358
assert.throws(() => {
64-
espree.parse("/./u");
59+
espree.parse("/./u", { ecmaVersion: 5 });
6560
});
6661
});
6762

Diff for: tests/lib/tokenize.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,10 @@ import tildeOperatorTokens from "../fixtures/tokenize/tilde-operator.tokens.js";
3030

3131
describe("tokenize()", () => {
3232

33-
it("should have `ecmaVersion: 5` as default", () => {
34-
35-
// FIXME: is there a way to test that it isn't `ecmaVersion: 3`?
33+
it("should have latestEcmaVersion as default", () => {
3634

3735
// needs `ecmaVersion: 6` or higher
38-
assert.throws(() => {
39-
espree.tokenize("`template`");
40-
});
36+
espree.tokenize("`template`");
4137
});
4238

4339
it("should produce tokens when using let", () => {

0 commit comments

Comments
 (0)