turbopack_wasm/
source.rs

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