turbopack_core/chunk/
module_id_strategies.rs

1use anyhow::{Result, bail};
2use rustc_hash::FxHashMap;
3use turbo_tasks::{ResolvedVc, ValueToString, Vc};
4use turbo_tasks_hash::hash_xxh3_hash64;
5
6use super::ModuleId;
7use crate::{
8    ident::AssetIdent,
9    issue::{IssueExt, StyledString, module::ModuleIssue},
10};
11
12#[turbo_tasks::value_trait]
13pub trait ModuleIdStrategy {
14    fn get_module_id(self: Vc<Self>, ident: Vc<AssetIdent>) -> Vc<ModuleId>;
15}
16
17#[turbo_tasks::value]
18pub struct DevModuleIdStrategy;
19
20impl DevModuleIdStrategy {
21    pub fn new() -> Vc<Self> {
22        DevModuleIdStrategy {}.cell()
23    }
24
25    pub fn new_resolved() -> ResolvedVc<Self> {
26        DevModuleIdStrategy {}.resolved_cell()
27    }
28}
29
30#[turbo_tasks::value_impl]
31impl ModuleIdStrategy for DevModuleIdStrategy {
32    #[turbo_tasks::function]
33    async fn get_module_id(self: Vc<Self>, ident: Vc<AssetIdent>) -> Result<Vc<ModuleId>> {
34        Ok(ModuleId::String(ident.to_string().owned().await?).cell())
35    }
36}
37
38#[turbo_tasks::value(shared)]
39pub struct GlobalModuleIdStrategy {
40    pub module_id_map: FxHashMap<ResolvedVc<AssetIdent>, u64>,
41}
42
43#[turbo_tasks::value_impl]
44impl ModuleIdStrategy for GlobalModuleIdStrategy {
45    #[turbo_tasks::function]
46    async fn get_module_id(&self, ident: ResolvedVc<AssetIdent>) -> Result<Vc<ModuleId>> {
47        if let Some(module_id) = self.module_id_map.get(&ident) {
48            const JS_MAX_SAFE_INTEGER: u64 = (1u64 << 53) - 1;
49            if *module_id > JS_MAX_SAFE_INTEGER {
50                bail!("Numeric module id is too large: {}", module_id);
51            }
52            return Ok(ModuleId::Number(*module_id).cell());
53        }
54
55        let ident_string = ident.to_string().await?;
56        if !ident_string.ends_with("[app-client] (ecmascript, next/dynamic entry)") {
57            // TODO: This shouldn't happen, but is a temporary workaround to ignore next/dynamic
58            // imports of a server component from another server component.
59
60            ModuleIssue {
61                ident,
62                title: StyledString::Text(
63                    format!("ModuleId not found for ident: {ident_string:?}").into(),
64                )
65                .resolved_cell(),
66                description: StyledString::Text(
67                    format!("ModuleId not found for ident: {ident_string:?}").into(),
68                )
69                .resolved_cell(),
70            }
71            .resolved_cell()
72            .emit();
73        }
74
75        Ok(ModuleId::String(
76            hash_xxh3_hash64(ident.to_string().await?)
77                .to_string()
78                .into(),
79        )
80        .cell())
81    }
82}