turbopack_ecmascript/chunk_list/
merged_update.rs1use anyhow::Result;
14use serde::Serialize;
15use turbo_tasks::{FxIndexMap, FxIndexSet, Vc};
16use turbo_tasks_fs::rope::Rope;
17use turbopack_core::{chunk::ModuleId, code_builder::Code, source_map::GenerateSourceMap};
18
19#[derive(Serialize, Default)]
21#[serde(
22 tag = "type",
23 rename = "EcmascriptMergedUpdate",
24 rename_all = "camelCase"
25)]
26pub struct EcmascriptMergedUpdate<'a> {
27 #[serde(skip_serializing_if = "FxIndexMap::is_empty")]
29 pub entries: FxIndexMap<ModuleId, EcmascriptModuleEntry>,
30 #[serde(skip_serializing_if = "FxIndexMap::is_empty")]
32 pub chunks: FxIndexMap<&'a str, EcmascriptMergedChunkUpdate>,
33}
34
35impl EcmascriptMergedUpdate<'_> {
36 pub fn is_empty(&self) -> bool {
37 self.entries.is_empty() && self.chunks.is_empty()
38 }
39}
40
41#[derive(Serialize)]
43#[serde(tag = "type", rename_all = "camelCase")]
44pub enum EcmascriptMergedChunkUpdate {
45 Added(EcmascriptMergedChunkAdded),
46 Deleted(EcmascriptMergedChunkDeleted),
47 Partial(EcmascriptMergedChunkPartial),
48}
49
50#[derive(Serialize, Default)]
52#[serde(rename_all = "camelCase")]
53pub struct EcmascriptMergedChunkAdded {
54 #[serde(skip_serializing_if = "FxIndexSet::is_empty")]
55 pub modules: FxIndexSet<ModuleId>,
56}
57
58#[derive(Serialize, Default)]
60#[serde(rename_all = "camelCase")]
61pub struct EcmascriptMergedChunkDeleted {
62 #[serde(skip_serializing_if = "FxIndexSet::is_empty")]
66 pub modules: FxIndexSet<ModuleId>,
67}
68
69#[derive(Serialize, Default)]
72#[serde(rename_all = "camelCase")]
73pub struct EcmascriptMergedChunkPartial {
74 #[serde(skip_serializing_if = "FxIndexSet::is_empty")]
75 pub added: FxIndexSet<ModuleId>,
76 #[serde(skip_serializing_if = "FxIndexSet::is_empty")]
77 pub deleted: FxIndexSet<ModuleId>,
78}
79
80#[derive(Serialize)]
82pub struct EcmascriptModuleEntry {
83 #[serde(with = "turbo_tasks_fs::rope::ser_as_string")]
84 pub code: Rope,
85 pub url: String,
86 #[serde(with = "turbo_tasks_fs::rope::ser_option_as_string")]
87 pub map: Option<Rope>,
88}
89
90impl EcmascriptModuleEntry {
91 pub async fn from_code(id: &ModuleId, code: Vc<Code>, chunk_path: &str) -> Result<Self> {
92 let map = &*code.generate_source_map().await?;
93 let map = map.as_content().map(|f| f.content().clone());
94
95 #[derive(Serialize)]
97 struct Id<'a> {
98 id: &'a ModuleId,
99 }
100 let id = serde_qs::to_string(&Id { id }).unwrap();
101
102 Ok(EcmascriptModuleEntry {
103 code: code.await?.source_code().clone(),
105 url: format!("{}?{}", chunk_path, id),
106 map,
107 })
108 }
109}