diff --git a/.changeset/cuddly-fans-glow.md b/.changeset/cuddly-fans-glow.md new file mode 100644 index 000000000000..26c33ea19653 --- /dev/null +++ b/.changeset/cuddly-fans-glow.md @@ -0,0 +1,5 @@ +--- +"@rspack/binding": patch +--- + +fix: circular dependencies rebuild panic diff --git a/crates/rspack_core/src/compiler/hmr.rs b/crates/rspack_core/src/compiler/hmr.rs index 672180c25ed2..cdaaffebb12f 100644 --- a/crates/rspack_core/src/compiler/hmr.rs +++ b/crates/rspack_core/src/compiler/hmr.rs @@ -4,6 +4,7 @@ use std::{ path::PathBuf, }; +use rayon::prelude::*; use rspack_error::Result; use rspack_fs::AsyncWritableFileSystem; use rspack_identifier::{IdentifierMap, IdentifierSet}; @@ -55,26 +56,23 @@ where compilation: &Compilation, ) -> (IdentifierMap<(u64, String)>, IdentifierMap) { let modules_map = compilation - .module_graph - .modules() - .values() - .map(|module| { - let identifier = module.identifier(); - ( - identifier, - ( - compilation - .module_graph - .get_module_hash(&identifier) - .expect("Module hash expected"), - compilation - .chunk_graph - .get_module_id(identifier) - .as_deref() - .expect("should has module id") - .to_string(), - ), - ) + .chunk_graph + .chunk_graph_module_by_module_identifier + .par_iter() + .filter_map(|(identifier, cgm)| { + let module_hash = compilation.module_graph.get_module_hash(identifier); + let cid = cgm.id.as_deref(); + if let Some(module_hash) = module_hash && let Some(cid) = cid { + Some(( + *identifier, + ( + module_hash, + cid.to_string(), + ), + )) + } else { + None + } }) .collect::>(); diff --git a/packages/rspack/tests/hotCases/runtime/hmr-circular/a.js b/packages/rspack/tests/hotCases/runtime/hmr-circular/a.js new file mode 100644 index 000000000000..c3dd29015505 --- /dev/null +++ b/packages/rspack/tests/hotCases/runtime/hmr-circular/a.js @@ -0,0 +1,2 @@ +import "./b"; +export default "a.js"; diff --git a/packages/rspack/tests/hotCases/runtime/hmr-circular/b.js b/packages/rspack/tests/hotCases/runtime/hmr-circular/b.js new file mode 100644 index 000000000000..8b93e1c537f9 --- /dev/null +++ b/packages/rspack/tests/hotCases/runtime/hmr-circular/b.js @@ -0,0 +1,2 @@ +import "./a"; +export default "b.js"; diff --git a/packages/rspack/tests/hotCases/runtime/hmr-circular/changed-file.js b/packages/rspack/tests/hotCases/runtime/hmr-circular/changed-file.js new file mode 100644 index 000000000000..85d22aeb8b95 --- /dev/null +++ b/packages/rspack/tests/hotCases/runtime/hmr-circular/changed-file.js @@ -0,0 +1,4 @@ +// TODO: remove this file after cache. +const path = require("path"); + +module.exports = [path.resolve(__dirname, "./entry.js")]; diff --git a/packages/rspack/tests/hotCases/runtime/hmr-circular/entry.js b/packages/rspack/tests/hotCases/runtime/hmr-circular/entry.js new file mode 100644 index 000000000000..584a1ce00ebb --- /dev/null +++ b/packages/rspack/tests/hotCases/runtime/hmr-circular/entry.js @@ -0,0 +1,4 @@ +import './a'; +export default "entry.js" +--- +export default "new_entry.js" diff --git a/packages/rspack/tests/hotCases/runtime/hmr-circular/index.js b/packages/rspack/tests/hotCases/runtime/hmr-circular/index.js new file mode 100644 index 000000000000..264e04e86172 --- /dev/null +++ b/packages/rspack/tests/hotCases/runtime/hmr-circular/index.js @@ -0,0 +1,10 @@ +import entry from "./entry"; + +it("should not throw error when hmr remove circular dependencies", done => { + expect(entry).toBe("entry.js"); + module.hot.accept("./entry", () => { + expect(entry).toBe("new_entry.js"); + done(); + }); + NEXT(require("../../update")(done)); +});