Skip to content

feat(linter): support dynamic import() in no-restricted-imports#21486

Closed
costajohnt wants to merge 6 commits into
oxc-project:mainfrom
costajohnt:feat/no-restricted-imports-dynamic
Closed

feat(linter): support dynamic import() in no-restricted-imports#21486
costajohnt wants to merge 6 commits into
oxc-project:mainfrom
costajohnt:feat/no-restricted-imports-dynamic

Conversation

@costajohnt

Copy link
Copy Markdown
Contributor

Summary

  • Add ImportExpression handling to no-restricted-imports so that import('source') with string literal arguments is checked against configured paths and patterns
  • Only path-level restrictions apply — importNames filtering is skipped since dynamic imports have no named bindings

Why

The rule currently only handles static import/export declarations and TSImportEqualsDeclaration. Dynamic import() expressions bypass restrictions entirely, allowing restricted modules to be imported at runtime.

Design

The implementation follows the existing report_ts_import_equals_declaration_allowed() pattern, using the same get_string_literal_result() method on both RestrictedPath and RestrictedPattern. Non-string-literal arguments (variables, template literals with substitutions) are ignored since the source cannot be statically analyzed.

Test cases

Pass (4): non-matching source, non-string argument, importNames doesn't apply to dynamic import, template literal
Fail (5): simple string restriction, path with message, pattern with glob, pattern with group/message, regex pattern

Closes #21411

@costajohnt
costajohnt requested a review from camc314 as a code owner April 16, 2026 01:58
@github-actions github-actions Bot added A-linter Area - Linter C-enhancement Category - New feature or request labels Apr 16, 2026
@codspeed-hq

codspeed-hq Bot commented Apr 16, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 47 skipped benchmarks1


Comparing costajohnt:feat/no-restricted-imports-dynamic (4e28232) with main (e9ec7c6)

Open in CodSpeed

Footnotes

  1. 47 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Comment thread crates/oxc_linter/src/rules/eslint/no_restricted_imports.rs Outdated

@camc314 camc314 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change and should be behind an opt-in flag

ignore this

@camc314 camc314 self-assigned this Apr 16, 2026
@costajohnt
costajohnt force-pushed the feat/no-restricted-imports-dynamic branch from 68581ef to 70b3964 Compare April 16, 2026 22:14
costajohnt and others added 5 commits May 6, 2026 14:42
Add handling for `import()` expressions with string literal arguments
in the `no-restricted-imports` rule. When the source is a string
literal, it is checked against the configured `paths` and `patterns`
restrictions.

Note: `importNames` filtering does not apply to dynamic imports
since they have no named bindings — only path-level restrictions
are checked, matching the behavior of the existing
TSImportEqualsDeclaration handler.

Closes oxc-project#21411
Fixes clippy::needless_raw_string_hashes lint warnings in dynamic
import test strings.
@costajohnt
costajohnt force-pushed the feat/no-restricted-imports-dynamic branch from 685dfe7 to 9e9e138 Compare May 7, 2026 00:49
@camchenry camchenry self-assigned this May 12, 2026
@camchenry
camchenry requested a review from camc314 May 18, 2026 03:42
@camchenry

Copy link
Copy Markdown
Member

@camc314 @costajohnt I made some changes here:

  • importNames and allowImportNames now work as part of this PR. I've only implemented support for the common case of immediately destructuring since I think that represents the vast majority of usage. So things like const { DisallowedObject } = await import('foo') will be caught if "importNames": ["DisallowedObject"] is set.
    • Similarly, importPattern and allowImportNamePattern work the same way. But will still not match on dynamic values, only static.
  • Added more tests.

Also @camc314 just noting that this isn't technically a breaking change as we have defined it, since this is basically just adding support for "new" syntax which yields better analysis. https://oxc.rs/docs/guide/usage/linter/versioning.html#are-new-lint-errors-a-breaking-change

@costajohnt

Copy link
Copy Markdown
Contributor Author

Thanks for picking this up @camchenry, much appreciated. The destructure scope feels right to me. That pattern covers basically every real use of dynamic import I've seen, and chasing the dynamic key variants would have been a rabbit hole.

@costajohnt

Copy link
Copy Markdown
Contributor Author

Hey @camc314, when you have a minute could you take another look at this. Both of the points you raised back in April are in the diff now. The get_inner_expression call for handling cases like import('foo' as string) is at crates/oxc_linter/src/rules/eslint/no_restricted_imports.rs:962, and template literal support (literals with no interpolation) is the arm right below at line 964. @camchenry also pushed a follow-up commit on May 17 adding importNames and importPattern support.

CI is green and the change is mergeable. If you've moved on from this and want to drop the changes-requested review, no worries either way.

@camchenry camchenry removed their assignment Jun 20, 2026
@graphite-app graphite-app Bot closed this in #24029 Jul 3, 2026
@costajohnt
costajohnt deleted the feat/no-restricted-imports-dynamic branch July 19, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(linter): no-restricted-imports should support dynamic import() expressions

3 participants