import-js / import-js/eslint-plugin-import
import/no-cycle crashing with external ESM modules (TypeError: Cannot read properties of null)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 5.9k
- Forks
- 1.5k
- PR merge metrics
- No merged PRs in 30d
Description
Minimum reproduction here (see README).
The Issue
(Please note that eslint-import-resolver-exports has been patched in this project to provide some logs)
- Run
yarn lint:ok - Linting is completed successfully
- Run
yarn lint:not-ok - Linting fails with the following error:
Oops! Something went wrong! :(
ESLint: 8.57.1
TypeError: Cannot read properties of null (reading '/Users/username/repositories/eslint-plugin-import-issue-1/src/not-ok.js')
Occurred while linting /Users/username/repositories/eslint-plugin-import-issue-1/src/not-ok.js:1
Rule: "import/no-cycle"
at checkSourceValue (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint-plugin-import/lib/rules/no-cycle.js:116:59)
at checkSourceValue (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint-module-utils/moduleVisitor.js:32:5)
at checkSource (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint-module-utils/moduleVisitor.js:38:5)
at ruleErrorHandler (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/linter.js:1076:28)
at /Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/safe-emitter.js:45:58
at Array.forEach (<anonymous>)
at Object.emit (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
at NodeEventGenerator.applySelector (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/node-event-generator.js:297:26)
at NodeEventGenerator.applySelectors (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/node-event-generator.js:326:22)
at NodeEventGenerator.enterNode (/Users/username/repositories/eslint-plugin-import-issue-1/node_modules/eslint/lib/linter/node-event-generator.js:340:14)
The Details
yarn lint:oklints./src/ok.jsfile with the following content:
import {default as inquirer} from 'inquirer';
yarn lint:not-oklints./src/not-ok.jsfile with the following content:
import {default as figures} from 'figures';
inquirerhas the following relevantpackage.jsonfields:
{
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"main": "./dist/commonjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/commonjs/index.d.ts"
}
figureshas the following relevantpackage.jsonfields:
{
"type": "module",
"exports": {
"types": "./index.d.ts",
"default": "./index.js"
}
}
- The important main difference is that
inquireris a hybrid package with both ESM and CJS entry points, whetherfiguresis ESM only. - Using the following settings, we make so that
requirecondition is preferred overimportcondition:
{
"import/resolver": {
"exports": {
"require": true
}
}
}
-
So,
inquireris loaded in CJS format, whilefiguresis loaded in ESM, which is what is making ESLint crash. In fact, if we go into theindex.jsoffiguresand remove all ESM import/export statements, the issue goes away. -
So, it would seem that ESM is supported in project files, but not inside
node_modulesfiles, but the strange things are:- If we remove
eslint-import-resolver-exportsfrom the settings, the issue goes away, even if the resolver is doing its job flawlessly (see logs). But we loose support forexports. - The issue seems to not be present when using
eslint-import-resolver-typescript. - It is like if
eslint-import-resolver-exportswas missing something in the returned data or something.
- If we remove
Finally, the most strange thing to me is that if we tweak eslint-import-resolver-exports to skip external modules, or just figures in this case, the issue also goes away.
Also, the following makes the issue go away:
{
"import/no-cycle": [
"error",
{
"ignoreExternal": true
}
]
}
(even if, as a side effect, ignoreExternal seems to increase linting time instead of reducing it as I would have expected)
So, is import/no-cycle really checking external modules? Or it is just working because the external files are not being resolved in most cases?
Is it an issue with eslint-import-resolver-exports?
I am available to work on this (I already adopted eslint-import-resolver-exports and will publish an updated version of it in the future).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the linked minimum reproduction with yarn lint:ok and yarn lint:not-ok, then inspect lib/rules/no-cycle.js at checkSourceValue and the resolver data involved in the reported stack trace. Compare the behavior with and without eslint-import-resolver-exports, and confirm the fix by ensuring the external ESM case no longer crashes while cycle checking remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- eslint, javascript
- Domain
- devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100