Skip to main content

turbopack_wasm/
source.rs

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