turbopack_core/chunk/
chunk_id_strategy.rs

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