turbopack_ecmascript/
bytes_source_transform.rs1use std::io::Read;
2
3use anyhow::{Result, bail};
4use turbo_tasks::Vc;
5use turbo_tasks_fs::{File, FileContent};
6use turbopack_core::{
7 asset::{Asset, AssetContent},
8 context::AssetContext,
9 source::Source,
10 source_transform::SourceTransform,
11 virtual_source::VirtualSource,
12};
13
14use crate::utils::{StringifyJs, inline_source_map_comment};
15
16#[turbo_tasks::value]
21pub struct BytesSourceTransform;
22
23#[turbo_tasks::value_impl]
24impl BytesSourceTransform {
25 #[turbo_tasks::function]
26 pub fn new() -> Vc<Self> {
27 BytesSourceTransform.cell()
28 }
29}
30
31#[turbo_tasks::value_impl]
32impl SourceTransform for BytesSourceTransform {
33 #[turbo_tasks::function]
34 async fn transform(
35 self: Vc<Self>,
36 source: Vc<Box<dyn Source>>,
37 _asset_context: Vc<Box<dyn AssetContext>>,
38 ) -> Result<Vc<Box<dyn Source>>> {
39 let ident = source.ident();
40 let path = ident.path().await?;
41 let content = source.content().file_content().await?;
42 let bytes = match &*content {
43 FileContent::Content(data) => {
44 data.read().bytes().collect::<std::io::Result<Vec<u8>>>()?
45 }
46 FileContent::NotFound => {
47 bail!("File not found: {:?}", path);
48 }
49 };
50
51 let encoded = data_encoding::BASE64_NOPAD.encode(&bytes);
52
53 let code = format!(
56 r#"
57"use turbopack no side effects";
58
59const decode = Uint8Array.fromBase64 || function(base64) {{
60 const binaryString = atob(base64);
61 const buffer = new Uint8Array(binaryString.length);
62 for (let i = 0; i < binaryString.length; i++) {{
63 buffer[i] = binaryString.charCodeAt(i)
64 }}
65 return buffer
66}};
67
68export default decode({});
69{}"#,
70 StringifyJs(&encoded),
71 inline_source_map_comment(&path.path, "")
74 );
75
76 let new_ident = ident.rename_as(format!("{}.[bytes].mjs", path.path).into());
79
80 Ok(Vc::upcast(VirtualSource::new_with_ident(
81 new_ident,
82 AssetContent::file(FileContent::Content(File::from(code)).cell()),
83 )))
84 }
85}