Skip to main content

turbopack_core/
changed.rs

1use anyhow::Result;
2use turbo_tasks::{
3    Completion, Completions, ResolvedVc, TryJoinIterExt, Vc,
4    graph::{AdjacencyMap, GraphTraversal},
5};
6
7use crate::{asset::Asset, module::Module, reference::primary_referenced_modules};
8
9pub async fn get_referenced_modules(
10    parent: ResolvedVc<Box<dyn Module>>,
11) -> Result<impl Iterator<Item = ResolvedVc<Box<dyn Module>>> + Send> {
12    Ok(primary_referenced_modules(*parent)
13        .owned()
14        .await?
15        .into_iter())
16}
17
18/// Returns a completion that changes when any content of any asset in the whole
19/// asset graph changes.
20#[turbo_tasks::function]
21pub async fn any_source_content_changed_of_module(
22    root: ResolvedVc<Box<dyn Module>>,
23) -> Result<Vc<Completion>> {
24    let completions = AdjacencyMap::new()
25        .visit([root], get_referenced_modules)
26        .await
27        .completed()?
28        .into_postorder_topological()
29        .map(|m| source_changed(*m))
30        .map(|v| v.to_resolved())
31        .try_join()
32        .await?;
33
34    Ok(Vc::<Completions>::cell(completions).completed())
35}
36
37/// Returns a completion that changes when the content of the given asset
38/// changes.
39#[turbo_tasks::function]
40pub async fn content_changed(asset: Vc<Box<dyn Asset>>) -> Result<Vc<Completion>> {
41    // Reading the file content is enough to add as dependency
42    asset.content().file_content().await?;
43    Ok(Completion::new())
44}
45
46/// Returns a completion that changes when the content of the given asset
47/// changes.
48#[turbo_tasks::function]
49pub async fn source_changed(asset: Vc<Box<dyn Module>>) -> Result<Vc<Completion>> {
50    if let Some(source) = *asset.source().await? {
51        // Reading the file content is enough to add as dependency
52        source.content().file_content().await?;
53    }
54    Ok(Completion::new())
55}