Skip to content

fix(linter): Update import/no-named-as-default to allow named import if equivalent to the default import#19100

Merged
graphite-app[bot] merged 1 commit intomainfrom
fix-default-rule
Feb 10, 2026
Merged

fix(linter): Update import/no-named-as-default to allow named import if equivalent to the default import#19100
graphite-app[bot] merged 1 commit intomainfrom
fix-default-rule

Conversation

@connorshea
Copy link
Member

@connorshea connorshea commented Feb 7, 2026

Fixes #19099. The way this logically works is a bit weird, but basically the idea is that some libraries have exports done via re-export of the same identifier as both a named and default export. In that case, we should allow import name from 'foo.js'; and import { name } from 'foo.js';. This allows the rule to better match the upstream rule's behavior.

Confirmed by running the built binary from this branch against my issue reproduction repo and confirming it no longer had any violations.

/*
 * This is what the @testing-library/user-event package exports:
 * ```js
 * export { userEvent as default } from './setup';
 * export { userEvent } from './setup';
 * ```
 * 
 * It should not error when we import the default export as `userEvent`, because it refers to the same exact value as if we had imported it via `import { userEvent } from '@testing-library/user-event';`.
 */
import userEvent from '@testing-library/user-event';

// With oxlint 1.43.0 and earlier, it currently gets reported as a violation. The original ESLint rule does not report this.

AI Disclosure: Built with Claude Code, Opus 4.6. Based on the changes from the upstream rule.

@connorshea connorshea requested a review from camc314 as a code owner February 7, 2026 05:22
Copilot AI review requested due to automatic review settings February 7, 2026 05:22
@github-actions github-actions bot added A-linter Area - Linter C-bug Category - Bug labels Feb 7, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates Oxlint’s import/no-named-as-default rule to match upstream eslint-plugin-import behavior by not flagging default imports whose local name matches a named export when the module’s default and named exports are effectively the same re-export (fixes #19099).

Changes:

  • Add special-case logic to skip the warning when default + named exports are re-exported from the same source binding.
  • Add fixtures and test cases to cover the allowed and still-disallowed scenarios.
  • Update the snapshot output to include the new failing case.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/oxc_linter/src/rules/import/no_named_as_default.rs Implements the new “same re-export” exception and adds corresponding tests.
crates/oxc_linter/src/snapshots/import_no_named_as_default.snap Updates snapshots to reflect the added test case.
crates/oxc_linter/fixtures/import/re-export-default-and-named.js Fixture for the allowed scenario (default + named re-exported from same source).
crates/oxc_linter/fixtures/import/re-export-default-and-named-source.js Source fixture providing the shared binding.
crates/oxc_linter/fixtures/import/re-export-default-and-named-misleading.js Fixture for the disallowed scenario (default + named re-exported from different sources).

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 7, 2026

CodSpeed Performance Report

Merging this PR will not alter performance

Comparing fix-default-rule (934944d) with main (0befb95)1

Summary

✅ 47 untouched benchmarks
⏩ 3 skipped benchmarks2

Footnotes

  1. No successful run was found on main (7e8873b) during the generation of this report, so 0befb95 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 3 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.

@camc314
Copy link
Contributor

camc314 commented Feb 9, 2026

@connorshea I added an extra test case here: 12801d4

It currently passes, but i think it should report an error - am i right?

let me know and I can either fix it or revert the commit, thanks 🙏

@connorshea
Copy link
Member Author

You are correct I believe, yeah. I'll work on fixing this.

@connorshea
Copy link
Member Author

Added two more test cases to ensure this fix doesn't cause any unintended problems with any of these situations. Should be good to go now.

@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Feb 10, 2026
@camc314 camc314 self-assigned this Feb 10, 2026
Copy link
Contributor

camc314 commented Feb 10, 2026

Merge activity

…t if equivalent to the default import (#19100)

Fixes #19099. The way this logically works is a bit weird, but basically the idea is that some libraries have exports done via re-export of the same identifier as both a named _and_ default export. In that case, we should allow `import name from 'foo.js';` *and* `import { name } from 'foo.js';`. This allows the rule to better match the upstream rule's behavior.

Confirmed by running the built binary from this branch against [my issue reproduction repo](https://github.com/connorshea/oxlint-repro-default-export/blob/main/test.js) and confirming it no longer had any violations.

```js
/*
 * This is what the @testing-library/user-event package exports:
 * ```js
 * export { userEvent as default } from './setup';
 * export { userEvent } from './setup';
 * ```
 *
 * It should not error when we import the default export as `userEvent`, because it refers to the same exact value as if we had imported it via `import { userEvent } from '@testing-library/user-event';`.
 */
import userEvent from '@testing-library/user-event';

// With oxlint 1.43.0 and earlier, it currently gets reported as a violation. The original ESLint rule does not report this.
```

AI Disclosure: Built with Claude Code, Opus 4.6. Based on [the changes from the upstream rule](https://github.com/import-js/eslint-plugin-import/pull/3032/changes).
@graphite-app graphite-app bot merged commit 31b562f into main Feb 10, 2026
21 checks passed
@graphite-app graphite-app bot deleted the fix-default-rule branch February 10, 2026 21:21
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Feb 10, 2026
owjs3901 pushed a commit to owjs3901/oxc that referenced this pull request Feb 11, 2026
…t if equivalent to the default import (oxc-project#19100)

Fixes oxc-project#19099. The way this logically works is a bit weird, but basically the idea is that some libraries have exports done via re-export of the same identifier as both a named _and_ default export. In that case, we should allow `import name from 'foo.js';` *and* `import { name } from 'foo.js';`. This allows the rule to better match the upstream rule's behavior.

Confirmed by running the built binary from this branch against [my issue reproduction repo](https://github.com/connorshea/oxlint-repro-default-export/blob/main/test.js) and confirming it no longer had any violations.

```js
/*
 * This is what the @testing-library/user-event package exports:
 * ```js
 * export { userEvent as default } from './setup';
 * export { userEvent } from './setup';
 * ```
 *
 * It should not error when we import the default export as `userEvent`, because it refers to the same exact value as if we had imported it via `import { userEvent } from '@testing-library/user-event';`.
 */
import userEvent from '@testing-library/user-event';

// With oxlint 1.43.0 and earlier, it currently gets reported as a violation. The original ESLint rule does not report this.
```

AI Disclosure: Built with Claude Code, Opus 4.6. Based on [the changes from the upstream rule](https://github.com/import-js/eslint-plugin-import/pull/3032/changes).
camc314 added a commit that referenced this pull request Feb 12, 2026
# Oxlint
### 🚀 Features

- ebb80b3 ast: Add `node_id` field to all AST struct nodes (#18138)
(Boshen)
- 2879fc5 linter: Implement fixer for unicorn/prefer-math-trunc (#19275)
(camc314)
- a204eda linter: Implement fixer for unicorn/no-typeof-undefined
(#19274) (camc314)
- ab46d9c linter: Implement typescript/class-literal-property-style
(#19252) (Vincent R)
- 1a61f58 linter: Implement typescript/no-invalid-void-type (#19242)
(Vincent R)

### 🐛 Bug Fixes

- 45adda2 oxlint/lsp: Use blocking stdio in Oxlint (#19292)
(overlookmotel)
- 05bc855 linter/import: Count unique module sources in max-dependencies
(#19270) (camc314)
- 8566b44 linter: Check for preceeding token in math trunc fixer
(#19277) (camc314)
- f16f2b6 linter/import-no-cycle: Avoid traversal-order false negatives
with type-only edges (#19267) (camc314)
- d4937e7 linter: Recognize module-scoped callback refs as stable in
exhaustive-deps (#19220) (Sreetam Das)
- 140c9bd linter: Detect fallthrough from `default` when it is not the
last case (#19261) (Boshen)
- 740a009 linter: Accept digits after 'use' in hook names (#19254)
(Sreetam Das)
- 31b562f linter: Update `import/no-named-as-default` to allow named
import if equivalent to the default import (#19100) (connorshea)
- 79c82cc linter: Avoid applying object-level docs to nested object
methods in require-param (#19231) (camc314)

### ⚡ Performance

- 5670291 linter/class-literal-property-style: Avoid unneeded string
allocations (#19262) (camc314)
# Oxfmt
### 🚀 Features

- ebb80b3 ast: Add `node_id` field to all AST struct nodes (#18138)
(Boshen)

### 🐛 Bug Fixes

- 1957908 formatter: Avoid unnecessary parentheses for string literal in
labeled statement (#19272) (Dunqing)

Co-authored-by: camc314 <[email protected]>
OskarLebuda pushed a commit to OskarLebuda/oxc that referenced this pull request Feb 17, 2026
…t if equivalent to the default import (oxc-project#19100)

Fixes oxc-project#19099. The way this logically works is a bit weird, but basically the idea is that some libraries have exports done via re-export of the same identifier as both a named _and_ default export. In that case, we should allow `import name from 'foo.js';` *and* `import { name } from 'foo.js';`. This allows the rule to better match the upstream rule's behavior.

Confirmed by running the built binary from this branch against [my issue reproduction repo](https://github.com/connorshea/oxlint-repro-default-export/blob/main/test.js) and confirming it no longer had any violations.

```js
/*
 * This is what the @testing-library/user-event package exports:
 * ```js
 * export { userEvent as default } from './setup';
 * export { userEvent } from './setup';
 * ```
 *
 * It should not error when we import the default export as `userEvent`, because it refers to the same exact value as if we had imported it via `import { userEvent } from '@testing-library/user-event';`.
 */
import userEvent from '@testing-library/user-event';

// With oxlint 1.43.0 and earlier, it currently gets reported as a violation. The original ESLint rule does not report this.
```

AI Disclosure: Built with Claude Code, Opus 4.6. Based on [the changes from the upstream rule](https://github.com/import-js/eslint-plugin-import/pull/3032/changes).
OskarLebuda pushed a commit to OskarLebuda/oxc that referenced this pull request Feb 17, 2026
# Oxlint
### 🚀 Features

- ebb80b3 ast: Add `node_id` field to all AST struct nodes (oxc-project#18138)
(Boshen)
- 2879fc5 linter: Implement fixer for unicorn/prefer-math-trunc (oxc-project#19275)
(camc314)
- a204eda linter: Implement fixer for unicorn/no-typeof-undefined
(oxc-project#19274) (camc314)
- ab46d9c linter: Implement typescript/class-literal-property-style
(oxc-project#19252) (Vincent R)
- 1a61f58 linter: Implement typescript/no-invalid-void-type (oxc-project#19242)
(Vincent R)

### 🐛 Bug Fixes

- 45adda2 oxlint/lsp: Use blocking stdio in Oxlint (oxc-project#19292)
(overlookmotel)
- 05bc855 linter/import: Count unique module sources in max-dependencies
(oxc-project#19270) (camc314)
- 8566b44 linter: Check for preceeding token in math trunc fixer
(oxc-project#19277) (camc314)
- f16f2b6 linter/import-no-cycle: Avoid traversal-order false negatives
with type-only edges (oxc-project#19267) (camc314)
- d4937e7 linter: Recognize module-scoped callback refs as stable in
exhaustive-deps (oxc-project#19220) (Sreetam Das)
- 140c9bd linter: Detect fallthrough from `default` when it is not the
last case (oxc-project#19261) (Boshen)
- 740a009 linter: Accept digits after 'use' in hook names (oxc-project#19254)
(Sreetam Das)
- 31b562f linter: Update `import/no-named-as-default` to allow named
import if equivalent to the default import (oxc-project#19100) (connorshea)
- 79c82cc linter: Avoid applying object-level docs to nested object
methods in require-param (oxc-project#19231) (camc314)

### ⚡ Performance

- 5670291 linter/class-literal-property-style: Avoid unneeded string
allocations (oxc-project#19262) (camc314)
# Oxfmt
### 🚀 Features

- ebb80b3 ast: Add `node_id` field to all AST struct nodes (oxc-project#18138)
(Boshen)

### 🐛 Bug Fixes

- 1957908 formatter: Avoid unnecessary parentheses for string literal in
labeled statement (oxc-project#19272) (Dunqing)

Co-authored-by: camc314 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

linter: Difference in import/no-named-as-default rule behavior

2 participants

Comments