Skip to content

Comments

fix(hmr): preserve original import.meta.hot when no HMR context exists#4391

Merged
underfin merged 2 commits intorolldown:mainfrom
magic-akari:fix/issue-4390
May 2, 2025
Merged

fix(hmr): preserve original import.meta.hot when no HMR context exists#4391
underfin merged 2 commits intorolldown:mainfrom
magic-akari:fix/issue-4390

Conversation

@magic-akari
Copy link
Contributor

@magic-akari magic-akari commented May 1, 2025

Description

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of hot module replacement to prevent potential runtime errors when hot module references are missing.
  • Tests

    • Added new test files and configuration to verify correct behavior when accessing hot module replacement features.

@coderabbitai
Copy link

coderabbitai bot commented May 1, 2025

Walkthrough

The changes update the internal logic of the rewrite_import_meta_hot method to prevent a runtime panic when hmr_hot_ref is None, ensuring the method leaves the expression unchanged in this case. Additionally, a new test case is introduced under tests/rolldown/issues/4390/, including a minimal configuration and a JavaScript file that logs import.meta.hot to the console, to verify the fix for the reported crash.

Changes

File(s) Change Summary
crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs Modified rewrite_import_meta_hot to safely handle None for hmr_hot_ref by adding a conditional check.
crates/rolldown/tests/rolldown/issues/4390/_config.json
main.js
package.json
Added a new test case directory with minimal config and a script to log import.meta.hot for regression testing.

Sequence Diagram(s)

sequenceDiagram
    participant TestRunner
    participant ScopeHoistingFinalizer
    participant JSModule

    TestRunner->>JSModule: Execute main.js (logs import.meta.hot)
    JSModule->>ScopeHoistingFinalizer: Encounter import.meta.hot
    ScopeHoistingFinalizer->>ScopeHoistingFinalizer: Check hmr_hot_ref (may be None)
    alt hmr_hot_ref is Some
        ScopeHoistingFinalizer->>JSModule: Rewrite import.meta.hot
    else hmr_hot_ref is None
        ScopeHoistingFinalizer->>JSModule: Leave import.meta.hot unchanged
    end
    JSModule->>TestRunner: Output result (no crash)
Loading

Assessment against linked issues

Objective Addressed Explanation
Prevent crash when input contains import.meta.hot and hmr_hot_ref is None (#4390)
Output import.meta.hot as-is when HMR is not enabled (#4390)

Possibly related PRs

  • rolldown/rolldown#4370: Introduced the initial logic for rewrite_import_meta_hot and handling of hmr_hot_ref in scope hoisting.

Suggested reviewers

  • hyf0

Poem

A bug hopped in, caused quite a fright—
Option::unwrap() crashed out of sight!
Now with a check, the code’s more robust,
No more panics, in safety we trust.
Test bunnies rejoice, the patch is complete,
With import.meta.hot, there’s no defeat!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

@magic-akari magic-akari marked this pull request as ready for review May 1, 2025 11:44
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

🔭 Outside diff range comments (1)
crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs (1)

125-136: 💡 Verification agent

🧩 Analysis chain

Potential consistency issue with hmr_hot_ref handling

This method still unconditionally uses unwrap() on hmr_hot_ref which could cause panics in similar scenarios. Consider applying the same pattern used in rewrite_import_meta_hot for consistency and to prevent potential issues.


🏁 Script executed:

#!/bin/bash
# Verify if generate_stmt_of_init_module_hot_context is only called when hmr_hot_ref is Some
rg -A 3 -B 3 "generate_stmt_of_init_module_hot_context"

Length of output: 2686


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs

Length of output: 6596


🏁 Script executed:

#!/bin/bash
rg -n "struct ScopeHoistingFinalizer" -C 5 crates/rolldown/src/module_finalizers/scope_hoisting

Length of output: 2279


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' crates/rolldown/src/hmr/hmr_ast_finalizer.rs

Length of output: 7201


Guard unwrap on hmr_hot_ref in HMR scope-hoisting finalizer

The method generate_stmt_of_init_module_hot_context in
crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs unconditionally calls

self.ctx.module.ecma_view.hmr_hot_ref.unwrap()

even though generate_hmr_header only checks options.is_hmr_enabled() and not the presence of a hot-ref. If hmr_hot_ref is None, this will panic at runtime.

• File: crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs
Location: generate_stmt_of_init_module_hot_context (around line 125)
• File: same, in generate_hmr_header (around line 104) where the call to
generate_stmt_of_init_module_hot_context() lives

Suggested fix: only call into or unwrap the hot-ref when it’s actually Some, mirroring rewrite_import_meta_hot. For example:

--- a/crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs
+++ b/crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs
@@ pub fn generate_hmr_header(&self) -> Vec<ast::Statement<'ast>> {
-   // import.meta.hot = __rolldown_runtime__.createModuleHotContext(moduleId);
-   ret.push(self.generate_stmt_of_init_module_hot_context());
+   // import.meta.hot = __rolldown_runtime__.createModuleHotContext(moduleId);
+   if let Some(hot_ref) = self.ctx.module.ecma_view.hmr_hot_ref {
+     ret.push(self.generate_stmt_of_init_module_hot_context(hot_ref));
+   }
--- a/crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs
+++ b/crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs
@@-125,7 +125,7 @@ impl<'ast> ScopeHoistingFinalizer<'_, 'ast> {
   pub fn generate_stmt_of_init_module_hot_context(&self) -> ast::Statement<'ast> {
-    let hot_name = self.canonical_name_for(self.ctx.module.ecma_view.hmr_hot_ref.unwrap());
+  pub fn generate_stmt_of_init_module_hot_context(&self, hmr_hot_ref: SymbolId) -> ast::Statement<'ast> {
+    let hot_name = self.canonical_name_for(hmr_hot_ref);

This ensures we only unwrap when a hot context really exists and keeps consistency with rewrite_import_meta_hot.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a720367 and d66bbd3.

⛔ Files ignored due to path filters (2)
  • crates/rolldown/tests/rolldown/issues/4390/artifacts.snap is excluded by !**/*.snap
  • crates/rolldown/tests/snapshots/integration_rolldown__filename_with_hash.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • crates/rolldown/src/module_finalizers/scope_hoisting/hmr.rs (1 hunks)
  • crates/rolldown/tests/rolldown/issues/4390/_config.json (1 hunks)
  • crates/rolldown/tests/rolldown/issues/4390/main.js (1 hunks)
  • crates/rolldown/tests/rolldown/issues/4390/package.json (1 hunks)
🔇 Additional comments (3)
crates/rolldown/tests/rolldown/issues/4390/main.js (1)

1-1: Test looks good for verifying the fix

This test file is a simple but effective verification for the fix. It logs import.meta.hot to console, which is exactly what's needed to confirm that accessing import.meta.hot doesn't cause a runtime panic when no HMR context exists.

crates/rolldown/tests/rolldown/issues/4390/_config.json (1)

1-3: Empty config is appropriate for this test

The empty configuration is suitable for this test case since we don't need any special configuration to test the basic behavior of import.meta.hot. This ensures the test runs with default settings, which is what we want to verify.

crates/rolldown/tests/rolldown/issues/4390/package.json (1)

1-3: Minimal package.json is sufficient

The minimal package definition with just a name is appropriate for this test. No additional configuration is needed to reproduce and verify the fix for import.meta.hot handling.

@underfin underfin enabled auto-merge May 1, 2025 15:27
@underfin underfin added this pull request to the merge queue May 2, 2025
Merged via the queue into rolldown:main with commit bc78fa1 May 2, 2025
30 checks passed
@codspeed-hq
Copy link

codspeed-hq bot commented May 2, 2025

CodSpeed Performance Report

Merging #4391 will improve performances by 5.38%

Comparing magic-akari:fix/issue-4390 (d66bbd3) with main (0de485b)

Summary

⚡ 1 improvements
✅ 20 untouched benchmarks

Benchmarks breakdown

Benchmark BASE HEAD Change
bundle@multi-duplicated-top-level-symbol 279.5 ms 265.3 ms +5.38%

@magic-akari magic-akari deleted the fix/issue-4390 branch May 2, 2025 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: crash with called Option::unwrap() on a None value when input contains import.meta.hot

2 participants