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
16pub mod debug;
17pub mod embed_js;
18pub mod evaluate;
19pub mod execution_context;
20mod heap_queue;
21mod pool;
22pub mod source_map;
23pub mod transforms;
24
25#[turbo_tasks::function]
26async fn emit(
27    intermediate_asset: Vc<Box<dyn OutputAsset>>,
28    intermediate_output_path: FileSystemPath,
29) -> Result<()> {
30    for asset in internal_assets(intermediate_asset, intermediate_output_path).await? {
31        let _ = asset
32            .content()
33            .write(asset.path().owned().await?)
34            .resolve()
35            .await?;
36    }
37    Ok(())
38}
39
40/// Extracts the subgraph of "internal" assets (assets within the passes
41/// directory). Also lists all boundary assets that are not part of the
42/// "internal" subgraph.
43#[turbo_tasks::function]
44async fn internal_assets(
45    intermediate_asset: ResolvedVc<Box<dyn OutputAsset>>,
46    intermediate_output_path: FileSystemPath,
47) -> Result<Vc<OutputAssets>> {
48    let all_assets = expand_output_assets(
49        std::iter::once(ExpandOutputAssetsInput::Asset(intermediate_asset)),
50        true,
51    )
52    .await?;
53    let internal_assets = all_assets
54        .into_iter()
55        .map(async |asset| {
56            let path = asset.path().await?;
57            if path.is_inside_ref(&intermediate_output_path) {
58                Ok(Some(asset))
59            } else {
60                Ok(None)
61            }
62        })
63        .try_flat_join()
64        .await?;
65    Ok(Vc::cell(internal_assets))
66}
67
68#[turbo_tasks::value(transparent)]
69pub struct AssetsForSourceMapping(FxHashMap<String, ResolvedVc<Box<dyn GenerateSourceMap>>>);
70
71/// Extracts a map of "internal" assets ([`internal_assets`]) which implement
72/// the [GenerateSourceMap] trait.
73#[turbo_tasks::function]
74async fn internal_assets_for_source_mapping(
75    intermediate_asset: Vc<Box<dyn OutputAsset>>,
76    intermediate_output_path: FileSystemPath,
77) -> Result<Vc<AssetsForSourceMapping>> {
78    let internal_assets =
79        internal_assets(intermediate_asset, intermediate_output_path.clone()).await?;
80    let intermediate_output_path = intermediate_output_path.clone();
81    let mut internal_assets_for_source_mapping = FxHashMap::default();
82    for asset in internal_assets.iter() {
83        if let Some(generate_source_map) =
84            ResolvedVc::try_sidecast::<Box<dyn GenerateSourceMap>>(*asset)
85            && let Some(path) = intermediate_output_path.get_path_to(&*asset.path().await?)
86        {
87            internal_assets_for_source_mapping.insert(path.to_string(), generate_source_map);
88        }
89    }
90    Ok(Vc::cell(internal_assets_for_source_mapping))
91}
92
93/// Emit a basic package.json that sets the type of the package to commonjs.
94/// Currently code generated for Node is CommonJS, while authored code may be
95/// ESM, for example.
96fn emit_package_json(dir: FileSystemPath) -> Result<Vc<()>> {
97    Ok(emit(
98        Vc::upcast(VirtualOutputAsset::new(
99            dir.join("package.json")?,
100            AssetContent::file(FileContent::Content(File::from("{\"type\": \"commonjs\"}")).cell()),
101        )),
102        dir,
103    ))
104}