Skip to content

Commit 0fe7fc1

Browse files
committed
[Fix]: no-cycle: check cycle for require even if option is set
1 parent d2ab3c1 commit 0fe7fc1

File tree

2 files changed

+115
-99
lines changed

2 files changed

+115
-99
lines changed

src/rules/no-cycle.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ module.exports = {
5858
return; // ignore external modules
5959
}
6060
if (options.allowUnsafeDynamicCyclicDependency && (
61-
importer.type === 'ImportExpression' || importer.type === 'CallExpression')) {
61+
// Ignore `import()`
62+
importer.type === 'ImportExpression' ||
63+
// `require()` calls are always checked (if possible)
64+
(importer.type === 'CallExpression' && importer.callee.name !== 'require'))) {
6265
return; // cycle via dynamic import allowed by config
6366
}
6467

tests/src/rules/no-cycle.js

Lines changed: 111 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -136,104 +136,117 @@ ruleTester.run('no-cycle', rule, {
136136
},
137137
}),
138138

139-
flatMap(testDialects, (testDialect) => [
140-
test({
141-
code: `import { foo } from "./${testDialect}/depth-one"`,
142-
errors: [error(`Dependency cycle detected.`)],
143-
}),
144-
test({
145-
code: `import { foo } from "./${testDialect}/depth-one"`,
146-
options: [{ maxDepth: 1 }],
147-
errors: [error(`Dependency cycle detected.`)],
148-
}),
149-
test({
150-
code: `const { foo } = require("./${testDialect}/depth-one")`,
151-
errors: [error(`Dependency cycle detected.`)],
152-
options: [{ commonjs: true }],
153-
}),
154-
test({
155-
code: `require(["./${testDialect}/depth-one"], d1 => {})`,
156-
errors: [error(`Dependency cycle detected.`)],
157-
options: [{ amd: true }],
158-
}),
159-
test({
160-
code: `define(["./${testDialect}/depth-one"], d1 => {})`,
161-
errors: [error(`Dependency cycle detected.`)],
162-
options: [{ amd: true }],
163-
}),
164-
test({
165-
code: `import { foo } from "./${testDialect}/depth-two"`,
166-
errors: [error(`Dependency cycle via ./depth-one:1`)],
167-
}),
168-
test({
169-
code: `import { foo } from "./${testDialect}/depth-two"`,
170-
options: [{ maxDepth: 2 }],
171-
errors: [error(`Dependency cycle via ./depth-one:1`)],
172-
}),
173-
test({
174-
code: `const { foo } = require("./${testDialect}/depth-two")`,
175-
errors: [error(`Dependency cycle via ./depth-one:1`)],
176-
options: [{ commonjs: true }],
177-
}),
178-
test({
179-
code: `import { two } from "./${testDialect}/depth-three-star"`,
180-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
181-
}),
182-
test({
183-
code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
184-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
185-
}),
186-
test({
187-
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
188-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
189-
}),
190-
test({
191-
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
192-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
193-
parser: parsers.BABEL_OLD,
194-
}),
195-
test({
196-
code: `import("./${testDialect}/depth-three-star")`,
197-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
198-
parser: parsers.BABEL_OLD,
199-
}),
200-
test({
201-
code: `import("./${testDialect}/depth-three-indirect")`,
202-
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
203-
parser: parsers.BABEL_OLD,
204-
}),
205-
test({
206-
code: `import { foo } from "./${testDialect}/depth-two"`,
207-
options: [{ maxDepth: Infinity }],
208-
errors: [error(`Dependency cycle via ./depth-one:1`)],
209-
}),
210-
test({
211-
code: `import { foo } from "./${testDialect}/depth-two"`,
212-
options: [{ maxDepth: '∞' }],
213-
errors: [error(`Dependency cycle via ./depth-one:1`)],
214-
}),
215-
test({
216-
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
217-
errors: [error(`Dependency cycle detected.`)],
218-
parser: parsers.BABEL_OLD,
219-
}),
220-
testVersion('> 3', () => ({ // Dynamic import is not properly caracterized with eslint < 4
221-
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 6`,
222-
errors: [error(`Dependency cycle detected.`)],
223-
parser: parsers.BABEL_OLD,
224-
})),
225-
].concat(parsers.TS_NEW ? [
226-
test({
227-
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 7`,
228-
errors: [error(`Dependency cycle detected.`)],
229-
parser: parsers.TS_NEW,
230-
}),
231-
test({
232-
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 8`,
233-
errors: [error(`Dependency cycle detected.`)],
234-
parser: parsers.TS_NEW,
235-
}),
236-
] : [])),
139+
flatMap(testDialects, (testDialect) =>
140+
// Ensure behavior does not change for those tests, with or without `
141+
flatMap([
142+
{},
143+
{ allowUnsafeDynamicCyclicDependency: true },
144+
], (opts) => [
145+
test({
146+
code: `import { foo } from "./${testDialect}/depth-one"`,
147+
options: [{ ...opts }],
148+
errors: [error(`Dependency cycle detected.`)],
149+
}),
150+
test({
151+
code: `import { foo } from "./${testDialect}/depth-one"`,
152+
options: [{ ...opts, maxDepth: 1 }],
153+
errors: [error(`Dependency cycle detected.`)],
154+
}),
155+
test({
156+
code: `const { foo } = require("./${testDialect}/depth-one")`,
157+
errors: [error(`Dependency cycle detected.`)],
158+
options: [{ ...opts, commonjs: true }],
159+
}),
160+
test({
161+
code: `require(["./${testDialect}/depth-one"], d1 => {})`,
162+
errors: [error(`Dependency cycle detected.`)],
163+
options: [{ ...opts, amd: true }],
164+
}),
165+
test({
166+
code: `define(["./${testDialect}/depth-one"], d1 => {})`,
167+
errors: [error(`Dependency cycle detected.`)],
168+
options: [{ ...opts, amd: true }],
169+
}),
170+
test({
171+
code: `import { foo } from "./${testDialect}/depth-two"`,
172+
options: [{ ...opts }],
173+
errors: [error(`Dependency cycle via ./depth-one:1`)],
174+
}),
175+
test({
176+
code: `import { foo } from "./${testDialect}/depth-two"`,
177+
options: [{ ...opts, maxDepth: 2 }],
178+
errors: [error(`Dependency cycle via ./depth-one:1`)],
179+
}),
180+
test({
181+
code: `const { foo } = require("./${testDialect}/depth-two")`,
182+
errors: [error(`Dependency cycle via ./depth-one:1`)],
183+
options: [{ ...opts, commonjs: true }],
184+
}),
185+
test({
186+
code: `import { two } from "./${testDialect}/depth-three-star"`,
187+
options: [{ ...opts }],
188+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
189+
}),
190+
test({
191+
code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
192+
options: [{ ...opts }],
193+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
194+
}),
195+
test({
196+
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
197+
options: [{ ...opts }],
198+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
199+
}),
200+
test({
201+
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
202+
options: [{ ...opts }],
203+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
204+
parser: parsers.BABEL_OLD,
205+
}),
206+
test({
207+
code: `import { foo } from "./${testDialect}/depth-two"`,
208+
options: [{ ...opts, maxDepth: Infinity }],
209+
errors: [error(`Dependency cycle via ./depth-one:1`)],
210+
}),
211+
test({
212+
code: `import { foo } from "./${testDialect}/depth-two"`,
213+
options: [{ ...opts, maxDepth: '∞' }],
214+
errors: [error(`Dependency cycle via ./depth-one:1`)],
215+
}),
216+
]).concat([
217+
test({
218+
code: `import("./${testDialect}/depth-three-star")`,
219+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
220+
parser: parsers.BABEL_OLD,
221+
}),
222+
test({
223+
code: `import("./${testDialect}/depth-three-indirect")`,
224+
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
225+
parser: parsers.BABEL_OLD,
226+
}),
227+
test({
228+
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
229+
errors: [error(`Dependency cycle detected.`)],
230+
parser: parsers.BABEL_OLD,
231+
}),
232+
]).concat(
233+
testVersion('> 3', () => ({ // Dynamic import is not properly caracterized with eslint < 4
234+
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 6`,
235+
errors: [error(`Dependency cycle detected.`)],
236+
parser: parsers.BABEL_OLD,
237+
})),
238+
).concat(parsers.TS_NEW ? [
239+
test({
240+
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 7`,
241+
errors: [error(`Dependency cycle detected.`)],
242+
parser: parsers.TS_NEW,
243+
}),
244+
test({
245+
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 8`,
246+
errors: [error(`Dependency cycle detected.`)],
247+
parser: parsers.TS_NEW,
248+
}),
249+
] : [])),
237250

238251
test({
239252
code: 'import { bar } from "./flow-types-depth-one"',

0 commit comments

Comments
 (0)