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,
30 Text,
32}
33
34#[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}