turbopack_ecmascript/chunk_list/
merged_update.rs1use anyhow::Result;
14use serde::Serialize;
15use turbo_frozenmap::{FrozenMap, FrozenSet};
16use turbo_rcstr::RcStr;
17use turbo_tasks::{NonLocalValue, Vc};
18use turbo_tasks_fs::rope::Rope;
19use turbopack_core::{chunk::ModuleId, code_builder::Code, source_map::GenerateSourceMap};
20
21#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
23#[serde(
24 tag = "type",
25 rename = "EcmascriptMergedUpdate",
26 rename_all = "camelCase"
27)]
28pub struct EcmascriptMergedUpdate {
29 #[serde(skip_serializing_if = "FrozenMap::is_empty")]
31 pub entries: FrozenMap<ModuleId, EcmascriptModuleEntry>,
32 #[serde(skip_serializing_if = "FrozenMap::is_empty")]
34 pub chunks: FrozenMap<RcStr, EcmascriptMergedChunkUpdate>,
35}
36
37impl EcmascriptMergedUpdate {
38 pub fn is_empty(&self) -> bool {
39 self.entries.is_empty() && self.chunks.is_empty()
40 }
41}
42
43#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
45#[serde(tag = "type", rename_all = "camelCase")]
46pub enum EcmascriptMergedChunkUpdate {
47 Added(EcmascriptMergedChunkAdded),
48 Deleted(EcmascriptMergedChunkDeleted),
49 Partial(EcmascriptMergedChunkPartial),
50}
51
52#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
54#[serde(rename_all = "camelCase")]
55pub struct EcmascriptMergedChunkAdded {
56 #[serde(skip_serializing_if = "FrozenSet::is_empty")]
57 pub modules: FrozenSet<ModuleId>,
58}
59
60#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
62#[serde(rename_all = "camelCase")]
63pub struct EcmascriptMergedChunkDeleted {
64 #[serde(skip_serializing_if = "FrozenSet::is_empty")]
68 pub modules: FrozenSet<ModuleId>,
69}
70
71#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
74#[serde(rename_all = "camelCase")]
75pub struct EcmascriptMergedChunkPartial {
76 #[serde(skip_serializing_if = "FrozenSet::is_empty")]
77 pub added: FrozenSet<ModuleId>,
78 #[serde(skip_serializing_if = "FrozenSet::is_empty")]
79 pub deleted: FrozenSet<ModuleId>,
80}
81
82#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, NonLocalValue)]
84pub struct EcmascriptModuleEntry {
85 #[serde(with = "turbo_tasks_fs::rope::ser_as_string")]
86 pub code: Rope,
87 pub url: RcStr,
88 #[serde(with = "turbo_tasks_fs::rope::ser_option_as_string")]
89 pub map: Option<Rope>,
90}
91
92impl EcmascriptModuleEntry {
93 pub async fn from_code(id: &ModuleId, code: Vc<Code>, chunk_path: &str) -> Result<Self> {
94 let map = &*code.generate_source_map().await?;
95 let map = map.as_content().map(|f| f.content().clone());
96
97 #[derive(Serialize)]
99 struct Id<'a> {
100 id: &'a ModuleId,
101 }
102 let id = serde_qs::to_string(&Id { id }).unwrap();
103
104 Ok(EcmascriptModuleEntry {
105 code: code.await?.source_code().clone(),
107 url: format!("{}?{}", chunk_path, id).into(),
108 map,
109 })
110 }
111}