Skip to main content

turbopack_node/
lib.rs

1#![feature(min_specialization)]
2#![feature(arbitrary_self_types)]
3#![feature(arbitrary_self_types_pointers)]
4
5use anyhow::Result;
6use rustc_hash::FxHashMap;
7use turbo_tasks::{ResolvedVc, TryFlatJoinIterExt, Vc};
8use turbo_tasks_fs::{File, FileContent, FileSystemPath};
9use turbopack_core::{
10    asset::{Asset, AssetContent},
11    output::{ExpandOutputAssetsInput, OutputAsset, OutputAssets, expand_output_assets},
12    source_map::GenerateSourceMap,
13    virtual_output::VirtualOutputAsset,
14};
15
16mod backend;
17pub mod debug;
18pub mod embed_js;
19pub mod evaluate;
20pub mod execution_context;
21mod format;
22mod pool_stats;
23#[cfg(feature = "process_pool")]
24pub mod process_pool;
25pub mod source_map;
26pub mod transforms;
27#[cfg(feature = "worker_pool")]
28pub mod worker_pool;
29
30pub use backend::{CreatePoolFuture, CreatePoolOptions, NodeBackend};
31#[cfg(feature = "process_pool")]
32pub fn child_process_backend() -> Vc<Box<dyn NodeBackend>> {
33    Vc::upcast(process_pool::ChildProcessesBackend.cell())
34}
35#[cfg(feature = "worker_pool")]
36pub fn worker_threads_backend() -> Vc<Box<dyn NodeBackend>> {
37    Vc::upcast(worker_pool::WorkerThreadsBackend.cell())
38}
39
40#[turbo_tasks::function]
41async fn emit(
42    intermediate_asset: Vc<Box<dyn OutputAsset>>,
43    intermediate_output_path: FileSystemPath,
44) -> Result<()> {
45    for asset in internal_assets(intermediate_asset, intermediate_output_path).await? {
46        let _ = asset
47            .content()
48            .write(asset.path().owned().await?)
49            .to_resolved()
50            .await?;
51    }
52    Ok(())
53}
54
55/// Extracts the subgraph of "internal" assets (assets within the passes
56/// directory). Also lists all boundary assets that are not part of the
57/// "internal" subgraph.
58#[turbo_tasks::function]
59async fn internal_assets(
60    intermediate_asset: ResolvedVc<Box<dyn OutputAsset>>,
61    intermediate_output_path: FileSystemPath,
62) -> Result<Vc<OutputAssets>> {
63    let all_assets = expand_output_assets(
64        std::iter::once(ExpandOutputAssetsInput::Asset(intermediate_asset)),
65        true,
66    )
67    .await?;
68    let internal_assets = all_assets
69        .into_iter()
70        .map(async |asset| {
71            let path = asset.path().await?;
72            if path.is_inside_ref(&intermediate_output_path) {
73                Ok(Some(asset))
74            } else {
75                Ok(None)
76            }
77        })
78        .try_flat_join()
79        .await?;
80    Ok(Vc::cell(internal_assets))
81}
82
83#[turbo_tasks::value(transparent)]
84pub struct AssetsForSourceMapping(FxHashMap<String, ResolvedVc<Box<dyn GenerateSourceMap>>>);
85
86/// Extracts a map of "internal" assets ([`internal_assets`]) which implement
87/// the [GenerateSourceMap] trait.
88#[turbo_tasks::function]
89async fn internal_assets_for_source_mapping(
90    intermediate_asset: Vc<Box<dyn OutputAsset>>,
91    intermediate_output_path: FileSystemPath,
92) -> Result<Vc<AssetsForSourceMapping>> {
93    let internal_assets =
94        internal_assets(intermediate_asset, intermediate_output_path.clone()).await?;
95    let intermediate_output_path = intermediate_output_path.clone();
96    let mut internal_assets_for_source_mapping = FxHashMap::default();
97    for asset in internal_assets.iter() {
98        if let Some(generate_source_map) =
99            ResolvedVc::try_sidecast::<Box<dyn GenerateSourceMap>>(*asset)
100            && let Some(path) = intermediate_output_path.get_path_to(&*asset.path().await?)
101        {
102            internal_assets_for_source_mapping.insert(path.to_string(), generate_source_map);
103        }
104    }
105    Ok(Vc::cell(internal_assets_for_source_mapping))
106}
107
108/// Emit a basic package.json that sets the type of the package to commonjs.
109/// Currently code generated for Node is CommonJS, while authored code may be
110/// ESM, for example.
111fn emit_package_json(dir: FileSystemPath) -> Result<Vc<()>> {
112    Ok(emit(
113        Vc::upcast(VirtualOutputAsset::new(
114            dir.join("package.json")?,
115            AssetContent::file(FileContent::Content(File::from("{\"type\": \"commonjs\"}")).cell()),
116        )),
117        dir,
118    ))
119}