From cbfab0af5cffd25dbbaaedf81745a4fc4e8521bd Mon Sep 17 00:00:00 2001 From: "Peter (Somogyvari) Metz" Date: Wed, 16 Jan 2019 11:03:58 -0800 Subject: [PATCH] New: adds flag to skip loading rules from FS This is a backward compatible change of the public API. By default the Linter class' constructor instantiates a Rules instance which (in its own constructor) has the side-effect of reading from the file-system to obtain rule files that may have been put there by the user. The issue with this is side-effect is that it breaks WebPack bundles (at runtime they crash when the Linter gets instantiated). The particular use-case that spawned this PR is running ESLint inside a WebPack bundle deployed onto an AWS Lambda function. The Linter is configured inline so there is no need to load any rules from the file-system. --- docs/developer-guide/nodejs-api.md | 13 +++++++++++++ lib/linter.js | 4 ++-- lib/rules.js | 6 ++++-- tests/lib/linter.js | 10 ++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md index 7b9ecb6ecfb1..49726b3b245d 100644 --- a/docs/developer-guide/nodejs-api.md +++ b/docs/developer-guide/nodejs-api.md @@ -9,6 +9,7 @@ While ESLint is designed to be run on the command line, it's possible to use ESL * [SourceCode](#sourcecode) * [splitLines()](#sourcecodesplitlines) * [Linter](#linter) + * [constructor()](#linterconstructor) * [verify()](#linterverify) * [verifyAndFix()](#linterverifyandfix) * [defineRule()](#linterdefinerule) @@ -87,6 +88,18 @@ var Linter = require("eslint").Linter; var linter = new Linter(); ``` +### Linter#constructor + +* `config.skipRulesLoadFromFs` If you are using the ESLint NodeJS API in code that you are packaging with a module bundler such as WebPack, then you may experience crashes when instantiating the Linter class due to it's default behavior to attempt to read the rule files from the file-system from a directory that does not exist (because the ESLint code was moved out of context by the bundler software). In a scenario like the above one, you will need to configure your Linter instance to skip the loading of the rules which you can do so by setting the `config.skipRulesLoadFromFs` parameter to boolean `true`. This allows you to configure your Linter instance "manually" from code. Note that you can still configure your Linter instance this way if your execution environment does have the correct directories in place on the file-system. + +```js +const Linter = require("eslint").Linter; +const config = { + skipRulesLoadFromFs: true // causes the Linter to skip reading rules from the file-system. +}; +const linter = new Linter(config); +``` + ### Linter#verify The most important method on `Linter` is `verify()`, which initiates linting of the given text. This method accepts three arguments: diff --git a/lib/linter.js b/lib/linter.js index d6d635f9f47d..f8435f12fa5c 100644 --- a/lib/linter.js +++ b/lib/linter.js @@ -769,12 +769,12 @@ const loadedParserMaps = new WeakMap(); */ module.exports = class Linter { - constructor() { + constructor(config = { skipRulesLoadFromFs: false }) { lastSourceCodes.set(this, null); loadedParserMaps.set(this, new Map()); this.version = pkg.version; - this.rules = new Rules(); + this.rules = new Rules({ skipRulesLoadFromFs: config.skipRulesLoadFromFs }); this.environments = new Environments(); } diff --git a/lib/rules.js b/lib/rules.js index 040f9db50594..dede42b8fd86 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -57,10 +57,12 @@ function normalizeRule(rule) { //------------------------------------------------------------------------------ class Rules { - constructor() { + constructor(config = { skipRulesLoadFromFs: false }) { this._rules = Object.create(null); - this.load(); + if (!config.skipRulesLoadFromFs) { + this.load(); + } } /** diff --git a/tests/lib/linter.js b/tests/lib/linter.js index ebe59625b058..9a3ecd900252 100644 --- a/tests/lib/linter.js +++ b/tests/lib/linter.js @@ -2771,6 +2771,16 @@ describe("Linter", () => { }); }); + describe("skips loading of rules from file-system if flag is passed in to constructor config", () => { + it("should return no loaded rules", () => { + const config = { skipRulesLoadFromFs: true }; + const emptyLinter = new Linter(config); + const rules = emptyLinter.getRules(); + + assert.strictEqual(rules.size, 0); + }); + }); + describe("when calling getRules", () => { it("should return all loaded rules", () => { const rules = linter.getRules();