diff --git a/turbopack/crates/turbopack-browser/src/chunking_context.rs b/turbopack/crates/turbopack-browser/src/chunking_context.rs index 4436802a0cf5..7ad018156ca7 100644 --- a/turbopack/crates/turbopack-browser/src/chunking_context.rs +++ b/turbopack/crates/turbopack-browser/src/chunking_context.rs @@ -20,7 +20,7 @@ use turbopack_core::{ chunk_id_strategy::ModuleIdStrategy, }, environment::Environment, - ident::AssetIdent, + ident::{AssetIdent, escape_file_path}, module::Module, module_graph::{ ModuleGraph, @@ -704,9 +704,10 @@ impl ChunkingContext for BrowserChunkingContext { match filename_template { Some(filename) => { let mut filename = filename.to_string(); + let name = escape_file_path(name); if match_name_placeholder(&filename) { - filename = replace_name_placeholder(&filename, name); + filename = replace_name_placeholder(&filename, &name); } if match_content_hash_placeholder(&filename) { @@ -808,9 +809,10 @@ impl ChunkingContext for BrowserChunkingContext { let mut filename = filename_template.to_string(); let (_, name, ext) = source_path.split_file_stem_extension(); + let name = escape_file_path(name); if match_name_placeholder(&filename) { - filename = replace_name_placeholder(&filename, name); + filename = replace_name_placeholder(&filename, &name); } if match_content_hash_placeholder(&filename) { diff --git a/turbopack/crates/turbopack-core/src/ident.rs b/turbopack/crates/turbopack-core/src/ident.rs index 7a25874bad92..8fa38b0ae14a 100644 --- a/turbopack/crates/turbopack-core/src/ident.rs +++ b/turbopack/crates/turbopack-core/src/ident.rs @@ -456,7 +456,7 @@ impl ValueToString for AssetIdent { pub fn escape_file_path(s: &str) -> String { static SEPARATOR_REGEX: LazyLock = - LazyLock::new(|| Regex::new(r"[/#?:\[\]<>@\s()]").unwrap()); + LazyLock::new(|| Regex::new(r"[/#?:\[\]<>@\s()&]").unwrap()); SEPARATOR_REGEX.replace_all(s, "_").to_string() } @@ -485,7 +485,7 @@ pub mod tests { let fs = VirtualFileSystem::new_with_name(rcstr!("test")); let root = fs.root().owned().await?; - let asset_ident = AssetIdent::from_path(root.join("a:b?c#d.js")?); + let asset_ident = AssetIdent::from_path(root.join("a:b?c#d&e.js")?); let output_name = asset_ident .output_name(root, Some(rcstr!("prefix")), rcstr!(".js")) .await?; @@ -493,7 +493,7 @@ pub mod tests { } let output_name = output_name_operation().read_strongly_consistent().await?; - assert_eq!(&*output_name, "prefix-a_b_c_d.js"); + assert_eq!(&*output_name, "prefix-a_b_c_d_e.js"); Ok(()) })