Skip to content

Conversation

@JounQin
Copy link
Member

@JounQin JounQin commented May 28, 2025

rework #116

https://nodejs.org/api/modules.html#all-together

LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_PACKAGE_EXPORTS(X, DIR)
   b. LOAD_AS_FILE(DIR/X)
   c. LOAD_AS_DIRECTORY(DIR/X)

Important

Fix module resolution to prioritize package exports over files and directories, aligning with Node.js spec.

  • Behavior:
    • Modify ResolverGeneric::load_node_modules in src/lib.rs to prioritize load_as_file before load_as_directory when specifier does not end with a slash.
    • Update prefer_file_over_pkg test to prefer_file_over_dir in src/tests/resolve.rs to reflect new resolution order.
  • Fixtures:
    • Rename prefer-file-over-pkg to prefer-file-over-dir in fixtures to align with updated test cases.
  • Tests:
    • Add test cases in src/tests/resolve.rs to verify new resolution order for package exports over files and directories.

This description was created by Ellipsis for bb2412c. You can customize this summary. It will automatically update as commits are pushed.


Summary by CodeRabbit

  • Bug Fixes
    • Improved package resolution inside node_modules, especially for specifiers without slashes or extensions, resulting in more accurate module loading and fewer resolution errors.
  • Tests
    • Expanded test coverage for module resolution with both unscoped and scoped package names, enhancing reliability.

@JounQin JounQin requested a review from Copilot May 28, 2025 12:04
@JounQin JounQin self-assigned this May 28, 2025
@JounQin JounQin added the bug Something isn't working label May 28, 2025
@coderabbitai
Copy link

coderabbitai bot commented May 28, 2025

Walkthrough

The update refines the logic in the load_node_modules method of the ResolverGeneric implementation. It changes the order and conditions under which file and directory resolution occurs for package specifiers, especially those without slashes, and removes the final unconditional file resolution fallback. Additionally, test coverage was expanded by renaming and modifying a test to cover both unscoped and scoped package resolutions with updated fixtures.

Changes

File(s) Change Summary
src/lib.rs Refactored load_node_modules logic: reordered file/directory resolution attempts, removed unconditional file fallback, refined handling of specifiers without slashes.
src/tests/resolve.rs Renamed test from prefer_file_over_pkg to prefer_file_over_dir; updated fixture path and expanded assertions to include scoped packages.
fixtures/prefer-file-over-dir/package.json Added new package.json fixture with minimal content for testing.
fixtures/prefer-file-over-pkg/package.json Deleted obsolete package.json fixture.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant ResolverGeneric

    Caller->>ResolverGeneric: load_node_modules(specifier)
    alt Cached path is file and alias_fields empty
        ResolverGeneric-->>Caller: Return cached file path
    else Specifier does not end with slash
        ResolverGeneric->>ResolverGeneric: load_as_file()
        alt File found
            ResolverGeneric-->>Caller: Return file path
        else
            alt Cached path is directory
                ResolverGeneric->>ResolverGeneric: load_browser_field_aliases_or_directory_index()
                alt Success
                    ResolverGeneric-->>Caller: Return directory result
                else
                    ResolverGeneric-->>Caller: Return error or fallback
                end
            else
                ResolverGeneric-->>Caller: Return error or fallback
            end
        end
    else
        alt Cached path is directory
            ResolverGeneric->>ResolverGeneric: load_browser_field_aliases_or_directory_index()
            ResolverGeneric-->>Caller: Return directory result
        else
            ResolverGeneric-->>Caller: Return error or fallback
        end
    end
Loading

Possibly related PRs

Poem

🐇 In node_modules, paths twist and wind,
Now slashes and files are better aligned.
No more guessing at the end of the trail—
The resolver checks twice, with logic less frail.
Hop, skip, and jump through the code we go,
With rabbits and modules, onward we flow! 🌿

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov
Copy link

codecov bot commented May 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.43%. Comparing base (e1c93e9) to head (bb2412c).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #118   +/-   ##
=======================================
  Coverage   93.42%   93.43%           
=======================================
  Files          13       13           
  Lines        2876     2879    +3     
=======================================
+ Hits         2687     2690    +3     
  Misses        189      189           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 0bcdede in 1 minute and 13 seconds. Click for details.
  • Reviewed 50 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/lib.rs:778
  • Draft comment:
    Ensure that package exports are prioritized per spec. Here the code calls load_package_exports before falling back to file/directory lookup—confirm this ordering matches Node.js behavior.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
2. src/lib.rs:833
  • Draft comment:
    There is a repeated call to load_as_directory on the same cached_path. Consider refactoring to avoid duplicate filesystem checks.
  • Reason this comment was not posted:
    Comment was on unchanged code.
3. src/lib.rs:797
  • Draft comment:
    The fallback logic for scoped packages (names beginning with '@') uses a parent's directory check. It would help to add a clarifying comment explaining the intent of this check.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_n9yHdRffO2RKAPIK

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

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

This PR updates the module resolution order to match the Node.js spec by trying package exports first, then falling back to file and directory resolution.

  • Removes the old early load_as_file block for bare specifiers
  • Inserts a unified check that first returns direct files, then calls load_as_file (if the specifier doesn’t end with a slash), before directory resolution
Comments suppressed due to low confidence (2)

src/lib.rs:820

  • [nitpick] The variable name no_slash is ambiguous. Consider renaming it to something like is_bare_specifier or has_no_path_segments for clarity.
let no_slash = !specifier.contains('/');

@codspeed-hq
Copy link

codspeed-hq bot commented May 28, 2025

CodSpeed Performance Report

Merging #118 will not alter performance

Comparing fix/try_exports_first (bb2412c) with main (e1c93e9)

Summary

✅ 3 untouched benchmarks

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1c93e9 and 0bcdede.

📒 Files selected for processing (1)
  • src/lib.rs (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Benchmark
  • GitHub Check: Test (windows-latest)
🔇 Additional comments (2)
src/lib.rs (2)

825-831: Good implementation of Node.js specification compliance.

This conditional logic correctly implements the Node.js module resolution algorithm by trying file resolution before directory resolution, and the condition no_slash || !specifier.ends_with('/') appropriately handles different specifier types.


786-791: Excellent alignment with Node.js specification order.

The overall flow now correctly follows the Node.js module resolution algorithm:

  1. Package exports first (lines 786-791)
  2. File resolution second (lines 827-831)
  3. Directory resolution last (lines 833-840)

This change brings the resolver in line with the official Node.js specification as intended.

Also applies to: 827-831, 833-840

@JounQin JounQin force-pushed the fix/try_exports_first branch from 0bcdede to bb2412c Compare May 28, 2025 12:24
@sonarqubecloud
Copy link

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed bb2412c in 1 minute and 1 seconds. Click for details.
  • Reviewed 92 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. fixtures/prefer-file-over-dir/package.json:3
  • Draft comment:
    Consider adding a trailing newline at the end of the file for consistency.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
2. src/tests/resolve.rs:39
  • Draft comment:
    Duplicate test entry for 'file in module with query and fragment' detected; consider removing one occurrence to avoid redundancy.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_zt8FvjADuprJkyR3

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@JounQin JounQin requested a review from Copilot May 28, 2025 12:31
Copy link

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

This PR reworks module resolution logic to prioritize package exports over file and directory resolution per the Node.js spec. It adjusts the resolution order in ResolverGeneric::load_node_modules, renames the test from "prefer_file_over_pkg" to "prefer_file_over_dir" (with corresponding fixture updates), and enhances test coverage for both unscoped and scoped package names.

Reviewed Changes

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

File Description
src/lib.rs Updated resolution order to check load_as_file before load_as_directory when the specifier does not end with a slash.
src/tests/resolve.rs Renamed test function and updated test cases to reflect new resolution behavior.
fixtures/prefer-file-over-dir Updated fixture naming to align with test expectations.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0bcdede and bb2412c.

⛔ Files ignored due to path filters (5)
  • fixtures/prefer-file-over-dir/node_modules/@foo/bar.js is excluded by !**/node_modules/**
  • fixtures/prefer-file-over-dir/node_modules/@foo/bar/index.js is excluded by !**/node_modules/**
  • fixtures/prefer-file-over-dir/node_modules/bar.js is excluded by !**/node_modules/**
  • fixtures/prefer-file-over-dir/node_modules/bar/index.js is excluded by !**/node_modules/**
  • fixtures/prefer-file-over-dir/node_modules/bar/package.json is excluded by !**/node_modules/**
📒 Files selected for processing (4)
  • fixtures/prefer-file-over-dir/package.json (1 hunks)
  • fixtures/prefer-file-over-pkg/package.json (0 hunks)
  • src/lib.rs (2 hunks)
  • src/tests/resolve.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • fixtures/prefer-file-over-pkg/package.json
✅ Files skipped from review due to trivial changes (1)
  • fixtures/prefer-file-over-dir/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib.rs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (2)
src/tests/resolve.rs (2)

122-122: Good naming improvement for test clarity.

The function name change from prefer_file_over_pkg to prefer_file_over_dir better reflects the actual behavior being tested - that files are preferred over directories in module resolution, which aligns with the Node.js specification changes mentioned in the PR.


123-123: Fixture path updated consistently.

The fixture directory path change maintains consistency with the renamed test function, which is good practice for test organization and maintainability.

@JounQin JounQin merged commit b19e7e8 into main May 28, 2025
22 checks passed
@JounQin JounQin deleted the fix/try_exports_first branch May 28, 2025 12:42
This was referenced May 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants