Skip to content

Bug: FlatESLint getRulesMetaForResults fails on anonymous files when option cwd is set #16410

Closed
@fasttime

Description

Environment

Node version: v18.10.0
npm version: v8.19.2
Local ESLint version: v8.25.0 (Currently used)
Global ESLint version: Not found
Operating System: darwin 21.6.0

What parser are you using?

Default (Espree)

What did you do?

Using FlatESLint, the method getRulesMetaForResults thows an error for certain values of the option cwd when passed a result of an anonymous file. This happens whenever cwd is set to a subdirectory of the current directory.

The following repro shows the problem.

import { join } from 'path';

const { default: { FlatESLint } } = await import('eslint/use-at-your-own-risk');

const cwd = join(process.cwd(), 'test'); // subdir 'test' doesn't need to exist for this repro.
const eslint = new FlatESLint({
    cwd,
    overrideConfig: { rules: { 'no-undef': 'warn' } },
    overrideConfigFile: true,
});
const results = await eslint.lintText('foo()');
eslint.getRulesMetaForResults(results); // throws TypeError

What did you expect to happen?

Calling getRulesMetaForResults with the result of an anonymous file should not throw an error, regardless of the engine's cwd.

What actually happened?

The above repro fails with an error like this:

.../node_modules/eslint/lib/config/flat-config-helpers.js:54
    const plugin = config.plugins && config.plugins[pluginName];
                          ^

TypeError: Cannot read properties of undefined (reading 'plugins')
    at getRuleFromConfig (.../node_modules/eslint/lib/config/flat-config-helpers.js:54:27)
    at FlatESLint.getRulesMetaForResults (.../node_modules/eslint/lib/eslint/flat-eslint.js:703:30)
    at file://.../example.mjs:12:8

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

What strikes me in the implementation are the different values used to call configs.getConfig in the case of an anonymous file: lintText calls configs.getConfig with a full path like ${cwd}/__placeholder__.js

const resolvedFilename = path.resolve(cwd, filePath || "__placeholder__.js");

whereas getRulesMetaForResults ends up calling configs.getConfig("__placeholder__.js")

/*
* Normalize filename for <text>.
*/
const filePath = result.filePath === "<text>"
? "__placeholder__.js" : result.filePath;
/*
* All of the plugin and rule information is contained within the
* calculated config for the given file.
*/
const config = configs.getConfig(filePath);

Then it finds no config and it fails.

Another issue related to this is the unhelpful message of the TypeError.
When getRulesMetaForResults finds no matching config, it could simply tell the user that the results were not created from the current instance of ESLint (not the case here, but still).
The error message is already there, but it is currently only used in a more limited edge case:

throw new TypeError("Results object was not created from this ESLint instance.");

Metadata

Assignees

No one assigned

    Labels

    acceptedThere is consensus among the team that this change meets the criteria for inclusionarchived due to ageThis issue has been archived; please open a new issue for any further discussionbugESLint is working incorrectlycoreRelates to ESLint's core APIs and featuresrepro:yesIssues with a reproducible example

    Type

    No type

    Projects

    • Status

      Complete

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions