Skip to content

Commit 3d020b9

Browse files
Update: emit a warning for ecmaFeatures rather than throwing an error (#8974)
(refs eslint/tsc-meetings#51 (comment)) Starting in 4.0.0, ESLint has been throwing a fatal error when encountering unexpected config file properties, including `ecmaFeatures`. However, many old configs still have the top-level `ecmaFeatures` option, which has had no effect since ESLint 1.x. This commit updates ESLint to emit a warning when it encounters a config with `ecmaFeatures`, rather than throwing an error.
1 parent d2f8f9f commit 3d020b9

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

conf/config-schema.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const baseConfigProperties = {
1212
parserOptions: { type: "object" },
1313
plugins: { type: "array" },
1414
rules: { type: "object" },
15-
settings: { type: "object" }
15+
settings: { type: "object" },
16+
17+
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
1618
};
1719

1820
const overrideProperties = Object.assign(

lib/config/config-validator.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//------------------------------------------------------------------------------
1111

1212
const ajv = require("../util/ajv"),
13+
lodash = require("lodash"),
1314
configSchema = require("../../conf/config-schema.js"),
1415
util = require("util");
1516

@@ -179,6 +180,25 @@ function formatErrors(errors) {
179180
}).map(message => `\t- ${message}.\n`).join("");
180181
}
181182

183+
/**
184+
* Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
185+
* for each unique file path, but repeated invocations with the same file path have no effect.
186+
* No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
187+
* @param {string} source The name of the configuration source to report the warning for.
188+
* @returns {void}
189+
*/
190+
const emitEcmaFeaturesWarning = lodash.memoize(source => {
191+
192+
/*
193+
* util.deprecate seems to be the only way to emit a warning in Node 4.x while respecting the --no-warnings flag.
194+
* (In Node 6+, process.emitWarning could be used instead.)
195+
*/
196+
util.deprecate(
197+
() => {},
198+
`[eslint] The 'ecmaFeatures' config file property is deprecated, and has no effect. (found in ${source})`
199+
)();
200+
});
201+
182202
/**
183203
* Validates the top level properties of the config object.
184204
* @param {Object} config The config object to validate.
@@ -191,6 +211,10 @@ function validateConfigSchema(config, source) {
191211
if (!validateSchema(config)) {
192212
throw new Error(`ESLint configuration in ${source} is invalid:\n${formatErrors(validateSchema.errors)}`);
193213
}
214+
215+
if (Object.prototype.hasOwnProperty.call(config, "ecmaFeatures")) {
216+
emitEcmaFeaturesWarning(source);
217+
}
194218
}
195219

196220
/**

tests/bin/eslint.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,28 @@ describe("bin/eslint.js", () => {
280280
});
281281
});
282282

283+
284+
describe("emitting a warning for ecmaFeatures", () => {
285+
it("does not emit a warning when it does not find an ecmaFeatures option", () => {
286+
const child = runESLint(["Makefile.js"]);
287+
288+
const exitCodePromise = assertExitCode(child, 0);
289+
const outputPromise = getOutput(child).then(output => assert.strictEqual(output.stderr, ""));
290+
291+
return Promise.all([exitCodePromise, outputPromise]);
292+
});
293+
it("emits a warning when it finds an ecmaFeatures option", () => {
294+
const child = runESLint(["-c", "tests/fixtures/config-file/ecma-features/.eslintrc.yml", "Makefile.js"]);
295+
296+
const exitCodePromise = assertExitCode(child, 0);
297+
const outputPromise = getOutput(child).then(output => {
298+
assert.include(output.stderr, "The 'ecmaFeatures' config file property is deprecated, and has no effect.");
299+
});
300+
301+
return Promise.all([exitCodePromise, outputPromise]);
302+
});
303+
});
304+
283305
afterEach(() => {
284306

285307
// Clean up all the processes after every test.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ecmaFeatures: {}

0 commit comments

Comments
 (0)