Skip to content

Commit e3ca68e

Browse files
ludofischerljharb
authored andcommitted
[Fix] named/ExportMap: handle named imports from CJS modules that use dynamic import
Fix #2294 Mark ambiguous (i.e. not unambiguously ESM) modules that contain dynamic import() so that they can be ignored like other ambiguous modules when analysing named imports. In this way, the named rule accepts named imports from CJS modules that contain dynamic imports. Also fix the case where the importing module uses a require() call.
1 parent ef980d4 commit e3ca68e

File tree

5 files changed

+29
-3
lines changed

5 files changed

+29
-3
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1010
- `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
1111
- [`first`]: prevent crash when parsing angular templates ([#2210], thanks [@ljharb])
1212
- `importType`: properly resolve `@/*`-aliased imports as internal ([#2334], thanks [@ombene])
13+
- [`named`]/`ExportMap`: handle named imports from CJS modules that use dynamic import ([#2341], thanks [@ludofischer])
1314

1415
### Changed
1516
- [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
@@ -951,6 +952,7 @@ for info on changes for earlier releases.
951952

952953
[`memo-parser`]: ./memo-parser/README.md
953954

955+
[#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
954956
[#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
955957
[#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
956958
[#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
@@ -1549,6 +1551,7 @@ for info on changes for earlier releases.
15491551
[@lo1tuma]: https://github.com/lo1tuma
15501552
[@loganfsmyth]: https://github.com/loganfsmyth
15511553
[@luczsoma]: https://github.com/luczsoma
1554+
[@ludofischer]: https://github.com/ludofischer
15521555
[@lukeapage]: https://github.com/lukeapage
15531556
[@lydell]: https://github.com/lydell
15541557
[@Mairu]: https://github.com/Mairu

src/ExportMap.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export default class ExportMap {
4343
*/
4444
this.imports = new Map();
4545
this.errors = [];
46+
/**
47+
* type {'ambiguous' | 'Module' | 'Script'}
48+
*/
49+
this.parseGoal = 'ambiguous';
4650
}
4751

4852
get hasDefault() { return this.get('default') != null; } // stronger than this.has
@@ -406,7 +410,8 @@ ExportMap.parse = function (path, content, context) {
406410
},
407411
});
408412

409-
if (!unambiguous.isModule(ast) && !hasDynamicImports) return null;
413+
const unambiguouslyESM = unambiguous.isModule(ast);
414+
if (!unambiguouslyESM && !hasDynamicImports) return null;
410415

411416
const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc'];
412417
const docStyleParsers = {};
@@ -710,6 +715,9 @@ ExportMap.parse = function (path, content, context) {
710715
m.namespace.set('default', {}); // add default export
711716
}
712717

718+
if (unambiguouslyESM) {
719+
m.parseGoal = 'Module';
720+
}
713721
return m;
714722
};
715723

src/rules/named.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module.exports = {
4040
}
4141

4242
const imports = Exports.get(node.source.value, context);
43-
if (imports == null) {
43+
if (imports == null || imports.parseGoal === 'ambiguous') {
4444
return;
4545
}
4646

@@ -97,6 +97,7 @@ module.exports = {
9797
// return if it's not a string source
9898
|| source.type !== 'Literal'
9999
|| variableExports == null
100+
|| variableExports.parseGoal === 'ambiguous'
100101
) {
101102
return;
102103
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
async function doSomething() {
2+
await import('./bar.js');
3+
}
4+
5+
exports.something = 'hello';

tests/src/rules/named.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,16 @@ ruleTester.run('named', rule, {
190190
sourceType: 'module',
191191
ecmaVersion: 2020,
192192
},
193-
})) || []),
193+
})),
194+
195+
testVersion('>=7.8.0', () =>({ code: 'const { something } = require("./dynamic-import-in-commonjs")',
196+
parserOptions: { ecmaVersion: 2021 },
197+
options: [{ commonjs: true }],
198+
})),
199+
200+
testVersion('>=7.8.0', () => ({ code: 'import { something } from "./dynamic-import-in-commonjs"',
201+
parserOptions: { ecmaVersion: 2021 } })),
202+
),
194203
],
195204

196205
invalid: [

0 commit comments

Comments
 (0)