Skip to main content

turbopack_wasm/
source.rs

1use anyhow::Result;
2use bincode::{Decode, Encode};
3use turbo_rcstr::RcStr;
4use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs};
5use turbo_tasks_fs::{File, FileContent};
6use turbopack_core::{
7    asset::{Asset, AssetContent},
8    ident::AssetIdent,
9    source::Source,
10};
11
12#[turbo_tasks::task_input]
13#[derive(PartialOrd, Ord, Eq, PartialEq, Hash, Debug, Copy, Clone, TraceRawVcs, Encode, Decode)]
14pub enum WebAssemblySourceType {
15    /// Binary WebAssembly files (.wasm).
16    Binary,
17    /// WebAssembly text format (.wat).
18    Text,
19}
20
21/// Returns the raw binary WebAssembly source or the assembled version of a text
22/// format source.
23#[turbo_tasks::value]
24#[derive(Clone)]
25pub struct WebAssemblySource {
26    source: ResolvedVc<Box<dyn Source>>,
27    source_ty: WebAssemblySourceType,
28}
29
30#[turbo_tasks::value_impl]
31impl WebAssemblySource {
32    #[turbo_tasks::function]
33    pub fn new(source: ResolvedVc<Box<dyn Source>>, source_ty: WebAssemblySourceType) -> Vc<Self> {
34        Self::cell(WebAssemblySource { source, source_ty })
35    }
36}
37
38#[turbo_tasks::value_impl]
39impl Source for WebAssemblySource {
40    #[turbo_tasks::function]
41    async fn ident(&self) -> Result<Vc<AssetIdent>> {
42        Ok(match self.source_ty {
43            WebAssemblySourceType::Binary => self.source.ident(),
44            WebAssemblySourceType::Text => {
45                let ident = self.source.ident().owned().await?;
46                let new_path = ident.path.append("_.wasm")?;
47                ident.with_path(new_path).into_vc()
48            }
49        })
50    }
51
52    #[turbo_tasks::function]
53    async fn description(&self) -> Result<Vc<RcStr>> {
54        let inner = self.source.description().await?;
55        Ok(Vc::cell(
56            format!("WebAssembly transform of {}", inner).into(),
57        ))
58    }
59}
60
61#[turbo_tasks::value_impl]
62impl Asset for WebAssemblySource {
63    #[turbo_tasks::function]
64    async fn content(&self) -> Result<Vc<AssetContent>> {
65        let content = match self.source_ty {
66            WebAssemblySourceType::Binary => return Ok(self.source.content()),
67            WebAssemblySourceType::Text => self.source.content(),
68        };
69
70        let content = content.file_content().await?;
71
72        let FileContent::Content(file) = &*content else {
73            return Ok(AssetContent::file(FileContent::NotFound.cell()));
74        };
75
76        let bytes = file.content().to_bytes();
77        let parsed = wat::parse_bytes(&bytes)?;
78
79        Ok(AssetContent::file(
80            FileContent::Content(File::from(&*parsed)).cell(),
81        ))
82    }
83}