turbopack_core/
changed.rs

1use anyhow::Result;
2use turbo_tasks::{
3    Completion, Completions, ResolvedVc, TryJoinIterExt, Vc,
4    graph::{GraphTraversal, NonDeterministic},
5};
6
7use crate::{
8    asset::Asset,
9    module::Module,
10    output::{OutputAsset, OutputAssets},
11    reference::primary_referenced_modules,
12};
13
14async fn get_referenced_output_assets(
15    parent: ResolvedVc<Box<dyn OutputAsset>>,
16) -> Result<impl Iterator<Item = ResolvedVc<Box<dyn OutputAsset>>> + Send> {
17    Ok(parent.references().owned().await?.into_iter())
18}
19
20pub async fn get_referenced_modules(
21    parent: ResolvedVc<Box<dyn Module>>,
22) -> Result<impl Iterator<Item = ResolvedVc<Box<dyn Module>>> + Send> {
23    Ok(primary_referenced_modules(*parent)
24        .owned()
25        .await?
26        .into_iter())
27}
28
29/// Returns a completion that changes when any content of any asset in the whole
30/// asset graph changes.
31#[turbo_tasks::function]
32pub async fn any_content_changed_of_module(
33    root: ResolvedVc<Box<dyn Module>>,
34) -> Result<Vc<Completion>> {
35    let completions = NonDeterministic::new()
36        .skip_duplicates()
37        .visit([root], get_referenced_modules)
38        .await
39        .completed()?
40        .into_inner()
41        .into_iter()
42        .map(|m| content_changed(*ResolvedVc::upcast(m)))
43        .map(|v| v.to_resolved())
44        .try_join()
45        .await?;
46
47    Ok(Vc::<Completions>::cell(completions).completed())
48}
49
50/// Returns a completion that changes when any content of any asset in the whole
51/// asset graph changes.
52#[turbo_tasks::function]
53pub async fn any_content_changed_of_output_asset(
54    root: ResolvedVc<Box<dyn OutputAsset>>,
55) -> Result<Vc<Completion>> {
56    let completions = NonDeterministic::new()
57        .skip_duplicates()
58        .visit([root], get_referenced_output_assets)
59        .await
60        .completed()?
61        .into_inner()
62        .into_iter()
63        .map(|m| content_changed(*ResolvedVc::upcast(m)))
64        .map(|v| v.to_resolved())
65        .try_join()
66        .await?;
67
68    Ok(Vc::<Completions>::cell(completions).completed())
69}
70
71/// Returns a completion that changes when any content of any asset in the given
72/// output asset graphs changes.
73#[turbo_tasks::function]
74pub async fn any_content_changed_of_output_assets(
75    roots: Vc<OutputAssets>,
76) -> Result<Vc<Completion>> {
77    Ok(Vc::<Completions>::cell(
78        roots
79            .await?
80            .iter()
81            .map(|&a| any_content_changed_of_output_asset(*a))
82            .map(|v| v.to_resolved())
83            .try_join()
84            .await?,
85    )
86    .completed())
87}
88
89/// Returns a completion that changes when the content of the given asset
90/// changes.
91#[turbo_tasks::function]
92pub async fn content_changed(asset: Vc<Box<dyn Asset>>) -> Result<Vc<Completion>> {
93    // Reading the file content is enough to add as dependency
94    asset.content().file_content().await?;
95    Ok(Completion::new())
96}