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