Skip to main content

turbopack_core/chunk/
chunk_id_strategy.rs

1use anyhow::Result;
2use bincode::{Decode, Encode};
3use rustc_hash::FxHashMap;
4use turbo_tasks::{
5    NonLocalValue, ResolvedVc, ValueToString, Vc, debug::ValueDebugFormat, trace::TraceRawVcs,
6    turbobail,
7};
8use turbo_tasks_hash::hash_xxh3_hash64;
9
10use super::ModuleId;
11use crate::{chunk::ChunkItem, ident::AssetIdent, module::Module};
12
13#[turbo_tasks::value(transparent, cell = "keyed")]
14pub struct ModuleIds(FxHashMap<ResolvedVc<AssetIdent>, ModuleId>);
15
16#[derive(
17    Default, Clone, PartialEq, Eq, ValueDebugFormat, TraceRawVcs, NonLocalValue, Encode, Decode,
18)]
19pub enum ModuleIdFallback {
20    Error,
21    #[default]
22    Ident,
23}
24
25#[turbo_tasks::value(shared)]
26#[derive(Default)]
27pub struct ModuleIdStrategy {
28    pub module_id_map: Option<ResolvedVc<ModuleIds>>,
29    pub fallback: ModuleIdFallback,
30}
31
32impl ModuleIdStrategy {
33    pub async fn get_id(&self, chunk_item: Vc<Box<dyn ChunkItem>>) -> Result<ModuleId> {
34        let ident = chunk_item.asset_ident();
35        self.get_id_from_ident(ident).await
36    }
37
38    pub async fn get_id_from_module(&self, module: Vc<Box<dyn Module>>) -> Result<ModuleId> {
39        let ident = module.ident();
40        self.get_id_from_ident(ident).await
41    }
42
43    pub async fn get_id_from_ident(&self, ident: Vc<AssetIdent>) -> Result<ModuleId> {
44        let ident = ident.to_resolved().await?;
45        if let Some(module_id_map) = self.module_id_map
46            && let Some(module_id) = module_id_map.get(&ident).await?.as_deref().cloned()
47        {
48            return Ok(module_id);
49        }
50
51        match self.fallback {
52            ModuleIdFallback::Error => {
53                let ident_string = ident.to_string().await?;
54                if ident_string.ends_with("[app-client] (ecmascript, next/dynamic entry)") {
55                    // TODO: This shouldn't happen, but is a temporary workaround to ignore
56                    // next/dynamic imports of a server component from another
57                    // server component.
58                    return Ok(ModuleId::String(
59                        hash_xxh3_hash64(ident.to_string().await?)
60                            .to_string()
61                            .into(),
62                    ));
63                }
64
65                turbobail!("ModuleId not found for ident: {}", ident);
66            }
67            ModuleIdFallback::Ident => Ok(ModuleId::String(ident.to_string().owned().await?)),
68        }
69    }
70}