Turbopack: unify ModuleGraph constructors (#93203)

We have options and variable length lists. Why do we need a separate
function for every combination?
This commit is contained in:
Niklas Mischkulnig
2026-04-24 18:42:04 +02:00
committed by GitHub
parent 5d3232fb2b
commit 3cb77c844b
11 changed files with 89 additions and 109 deletions
+5 -7
View File
@@ -966,7 +966,7 @@ impl AppProject {
graphs.push(graph);
visited_modules = VisitedModules::concatenate(visited_modules, graph);
let base = ModuleGraph::from_graphs(graphs.clone());
let base = ModuleGraph::from_graphs(graphs.clone(), None);
let additional_entries = endpoint.additional_entries(base.connect());
let additional_module_graph = SingleModuleGraph::new_with_entries_visited_intern(
additional_entries.owned().await?,
@@ -991,20 +991,18 @@ impl AppProject {
.await?;
let (full, binding_usage_info) = if remove_unused_imports {
let full_with_unused_references = ModuleGraph::from_graphs(graphs.clone());
let full_with_unused_references =
ModuleGraph::from_graphs(graphs.clone(), None);
let binding_usage_info = compute_binding_usage_info(
full_with_unused_references,
should_read_binding_usage,
);
(
ModuleGraph::from_graphs_without_unused_references(
graphs,
binding_usage_info,
),
ModuleGraph::from_graphs(graphs, Some(binding_usage_info)),
Some(binding_usage_info),
)
} else {
(ModuleGraph::from_graphs(graphs), None)
(ModuleGraph::from_graphs(graphs, None), None)
};
Ok(BaseAndFullModuleGraph {
+3 -3
View File
@@ -753,11 +753,11 @@ impl PageEndpoint {
.await?;
let graph = if remove_unused_imports {
let graph = ModuleGraph::from_graphs(graphs.clone());
let graph = ModuleGraph::from_graphs(graphs.clone(), None);
let binding_usage_info = compute_binding_usage_info(graph, true);
ModuleGraph::from_graphs_without_unused_references(graphs, binding_usage_info)
ModuleGraph::from_graphs(graphs, Some(binding_usage_info))
} else {
ModuleGraph::from_graphs(graphs)
ModuleGraph::from_graphs(graphs, None)
};
Ok(graph.connect())
+21 -18
View File
@@ -1452,11 +1452,14 @@ impl Project {
) -> Result<Vc<ModuleGraph>> {
Ok(if *self.per_page_module_graph().await? {
let is_production = self.next_mode().await?.is_production();
ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entry(
ChunkGroupEntry::Entry(vec![entry]),
is_production,
is_production,
))
ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entry(
ChunkGroupEntry::Entry(vec![entry]),
is_production,
is_production,
)],
None,
)
.connect()
} else {
*self.whole_app_module_graphs().await?.full
@@ -1476,11 +1479,14 @@ impl Project {
.copied()
.map(ResolvedVc::upcast)
.collect();
ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(entries)]),
is_production,
is_production,
))
ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entries(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(entries)]),
is_production,
is_production,
)],
None,
)
.connect()
} else {
*self.whole_app_module_graphs().await?.full
@@ -2490,7 +2496,7 @@ async fn whole_app_module_graph_operation(
);
let base_visited_modules = VisitedModules::from_graph(base_single_module_graph);
let base = ModuleGraph::from_single_graph(base_single_module_graph);
let base = ModuleGraph::from_graphs(vec![base_single_module_graph], None);
let turbopack_remove_unused_imports = *project
.next_config()
@@ -2501,10 +2507,7 @@ async fn whole_app_module_graph_operation(
// TODO suboptimal that we do compute_binding_usage_info twice (once for the base
// graph and later for the full graph)
let binding_usage_info = compute_binding_usage_info(base, true);
ModuleGraph::from_single_graph_without_unused_references(
base_single_module_graph,
binding_usage_info,
)
ModuleGraph::from_graphs(vec![base_single_module_graph], Some(binding_usage_info))
} else {
base
};
@@ -2540,14 +2543,14 @@ async fn whole_app_module_graph_operation(
let graphs = vec![base_single_module_graph, additional_module_graph];
let (full, binding_usage_info) = if turbopack_remove_unused_imports {
let full_with_unused_references = ModuleGraph::from_graphs(graphs.clone());
let full_with_unused_references = ModuleGraph::from_graphs(graphs.clone(), None);
let binding_usage_info = compute_binding_usage_info(full_with_unused_references, true);
(
ModuleGraph::from_graphs_without_unused_references(graphs, binding_usage_info),
ModuleGraph::from_graphs(graphs, Some(binding_usage_info)),
Some(binding_usage_info),
)
} else {
(ModuleGraph::from_graphs(graphs), None)
(ModuleGraph::from_graphs(graphs, None), None)
};
Ok(BaseAndFullModuleGraph {
+8 -5
View File
@@ -774,11 +774,14 @@ async fn get_mock_stylesheet(
.module();
let entries = get_evaluate_entries(mocked_response_asset, asset_context, *node_backend, None);
let module_graph = ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
));
let module_graph = ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
)],
None,
);
let module_graph = module_graph.connect();
let root = mock_fs.root().owned().await?;
@@ -316,15 +316,14 @@ async fn build_internal(
false,
true,
);
let mut module_graph = ModuleGraph::from_single_graph(single_graph);
let mut module_graph = ModuleGraph::from_graphs(vec![single_graph], None);
let binding_usage = compute_binding_usage_info(module_graph, true);
let unused_references = binding_usage
.connect()
.unused_references()
.to_resolved()
.await?;
module_graph =
ModuleGraph::from_single_graph_without_unused_references(single_graph, binding_usage);
module_graph = ModuleGraph::from_graphs(vec![single_graph], Some(binding_usage));
let module_graph = module_graph.connect();
let module_id_strategy = get_global_module_id_strategy(module_graph)
.to_resolved()
@@ -161,11 +161,14 @@ pub async fn create_web_entry_source(
.map(|&entry| ResolvedVc::upcast(entry)),
)
.collect::<Vec<ResolvedVc<Box<dyn Module>>>>();
let module_graph = ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(all_modules)]),
false,
false,
));
let module_graph = ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entries(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(all_modules)]),
false,
false,
)],
None,
);
let module_graph = module_graph.connect().to_resolved().await?;
let entries: Vec<_> = entries
@@ -698,56 +698,21 @@ pub struct ModuleGraph {
#[turbo_tasks::value_impl]
impl ModuleGraph {
/// Analyze the module graph and potentially remove unused references (by determining the used
/// exports and removing unused imports).
#[turbo_tasks::function(operation)]
pub async fn from_single_graph(graph: OperationVc<SingleModuleGraph>) -> Result<Vc<Self>> {
let graph = Self::create(vec![graph], None)
.read_strongly_consistent()
.await?;
Ok(ReadRef::cell(graph))
}
#[turbo_tasks::function(operation)]
pub async fn from_graphs(graphs: Vec<OperationVc<SingleModuleGraph>>) -> Result<Vc<Self>> {
let graph = Self::create(graphs, None)
.read_strongly_consistent()
.await?;
Ok(ReadRef::cell(graph))
}
/// Analyze the module graph and remove unused references (by determining the used exports and
/// removing unused imports).
///
/// In particular, this removes ModuleReference-s that list only unused exports in the
/// `import_usage()`
#[turbo_tasks::function(operation)]
pub async fn from_single_graph_without_unused_references(
graph: OperationVc<SingleModuleGraph>,
binding_usage: OperationVc<BindingUsageInfo>,
) -> Result<Vc<Self>> {
let graph = Self::create(vec![graph], Some(binding_usage))
.read_strongly_consistent()
.await?;
Ok(ReadRef::cell(graph))
}
/// Analyze the module graph and remove unused references (by determining the used exports and
/// removing unused imports).
///
/// In particular, this removes ModuleReference-s that list only unused exports in the
/// `import_usage()`
#[turbo_tasks::function(operation)]
pub async fn from_graphs_without_unused_references(
pub async fn from_graphs(
graphs: Vec<OperationVc<SingleModuleGraph>>,
binding_usage: OperationVc<BindingUsageInfo>,
binding_usage: Option<OperationVc<BindingUsageInfo>>,
) -> Result<Vc<Self>> {
let graph = Self::create(graphs, Some(binding_usage))
let graph = Self::from_graphs_inner(graphs, binding_usage)
.read_strongly_consistent()
.await?;
Ok(ReadRef::cell(graph))
}
#[turbo_tasks::function(operation)]
async fn create(
async fn from_graphs_inner(
graphs: Vec<OperationVc<SingleModuleGraph>>,
binding_usage: Option<OperationVc<BindingUsageInfo>>,
) -> Result<Vc<ModuleGraph>> {
@@ -2103,15 +2068,18 @@ pub mod tests {
false,
);
let module_graph = ModuleGraph::from_graphs(vec![
parent_graph,
SingleModuleGraph::new_with_entries_visited(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(vec![a_module])]),
VisitedModules::from_graph(parent_graph),
false,
false,
),
])
let module_graph = ModuleGraph::from_graphs(
vec![
parent_graph,
SingleModuleGraph::new_with_entries_visited(
ResolvedVc::cell(vec![ChunkGroupEntry::Entry(vec![a_module])]),
VisitedModules::from_graph(parent_graph),
false,
false,
),
],
None,
)
.connect();
let child_graph = module_graph
.iter_graphs()
@@ -2366,7 +2334,9 @@ pub mod tests {
.await?
.into_iter()
.collect();
let module_graph = ModuleGraph::from_single_graph(graph).connect().await?;
let module_graph = ModuleGraph::from_graphs(vec![graph], None)
.connect()
.await?;
Ok(SetupGraph {
module_graph,
@@ -546,11 +546,14 @@ impl PostCssTransformedAsset {
.to_resolved()
.await?;
let module_graph = ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
))
let module_graph = ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
)],
None,
)
.connect()
.to_resolved()
.await?;
@@ -274,11 +274,14 @@ impl WebpackLoadersProcessedAsset {
.to_resolved()
.await?;
let module_graph = ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
))
let module_graph = ModuleGraph::from_graphs(
vec![SingleModuleGraph::new_with_entries(
entries.graph_entries().to_resolved().await?,
false,
false,
)],
None,
)
.connect()
.to_resolved()
.await?;
@@ -715,7 +718,7 @@ impl EvaluateContext for WebpackLoaderContext {
false,
false,
);
let import_module_graph = ModuleGraph::from_single_graph(single_graph)
let import_module_graph = ModuleGraph::from_graphs(vec![single_graph], None)
.connect()
.to_resolved()
.await?;
@@ -517,7 +517,7 @@ async fn run_test_operation(prepared_test: ResolvedVc<PreparedTest>) -> Result<V
false,
true,
);
let mut module_graph = ModuleGraph::from_single_graph(single_graph);
let mut module_graph = ModuleGraph::from_graphs(vec![single_graph], None);
let binding_usage = if options.remove_unused_imports || options.remove_unused_exports {
Some(compute_binding_usage_info(
@@ -530,8 +530,7 @@ async fn run_test_operation(prepared_test: ResolvedVc<PreparedTest>) -> Result<V
if options.remove_unused_imports
&& let Some(binding_usage) = binding_usage
{
module_graph =
ModuleGraph::from_single_graph_without_unused_references(single_graph, binding_usage);
module_graph = ModuleGraph::from_graphs(vec![single_graph], Some(binding_usage));
}
let module_graph = module_graph.connect();
@@ -460,7 +460,7 @@ async fn run_test_operation(resource: RcStr) -> Result<Vc<FileSystemPath>> {
false,
true,
);
let mut module_graph = ModuleGraph::from_single_graph(single_graph);
let mut module_graph = ModuleGraph::from_graphs(vec![single_graph], None);
let binding_usage = if options.remove_unused_imports || options.remove_unused_exports {
Some(compute_binding_usage_info(
@@ -473,8 +473,7 @@ async fn run_test_operation(resource: RcStr) -> Result<Vc<FileSystemPath>> {
if options.remove_unused_imports
&& let Some(binding_usage) = binding_usage
{
module_graph =
ModuleGraph::from_single_graph_without_unused_references(single_graph, binding_usage);
module_graph = ModuleGraph::from_graphs(vec![single_graph], Some(binding_usage));
}
let module_graph = module_graph.connect();