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,
17 Text,
19}
20
21#[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}