Skip to content

Commit a3bb0e1

Browse files
committed
feat(turbo-tasks-fs): use tokio-fs-ext::offload on wasm
1 parent 8a22517 commit a3bb0e1

File tree

4 files changed

+75
-102
lines changed

4 files changed

+75
-102
lines changed

Cargo.lock

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

turbopack/crates/turbo-tasks-fs/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ urlencoding = { workspace = true }
5555
notify = { workspace = true }
5656

5757
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
58-
tokio-fs-ext = "0.3.11"
58+
tokio-fs-ext = "0.5.1"
59+
wasm_thread = { git = "https://github.com/utooland/wasm_thread.git", default-features = false, features = [
60+
"spawn_from_worker",
61+
] }
5962

6063
[dev-dependencies]
6164
criterion = { workspace = true, features = ["async_tokio"] }

turbopack/crates/turbo-tasks-fs/src/lib.rs

Lines changed: 49 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ use std::{
3737
time::Duration,
3838
};
3939

40+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
41+
pub mod wasm_fs_offload;
42+
4043
use anyhow::{Context, Result, anyhow, bail};
4144
use auto_hash_map::{AutoMap, AutoSet};
4245
use bitflags::bitflags;
@@ -584,13 +587,7 @@ impl FileSystem for DiskFileSystem {
584587
};
585588

586589
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
587-
let content = match tokio_fs_ext::read(full_path.clone())
588-
.instrument(tracing::info_span!(
589-
"read file",
590-
name = display(full_path.display())
591-
))
592-
.await
593-
{
590+
let content = match wasm_fs_offload::CLIENT.read(full_path.clone()).await {
594591
Ok(buf) => Ok(FileContent::from(File::from_bytes(buf))),
595592
Err(e) if e.kind() == ErrorKind::NotFound || e.kind() == ErrorKind::InvalidFilename => {
596593
Ok(FileContent::NotFound)
@@ -630,7 +627,21 @@ impl FileSystem for DiskFileSystem {
630627
}
631628
};
632629

633-
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
630+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
631+
let read_dir = match wasm_fs_offload::CLIENT.read_dir(full_path.clone()).await {
632+
Ok(dir) => dir,
633+
Err(e)
634+
if e.kind() == ErrorKind::NotFound
635+
|| e.kind() == ErrorKind::NotADirectory
636+
|| e.kind() == ErrorKind::InvalidFilename =>
637+
{
638+
return Ok(RawDirectoryContent::not_found());
639+
}
640+
Err(e) => {
641+
bail!(anyhow!(e).context(format!("reading dir {}", full_path.display())))
642+
}
643+
};
644+
634645
let entries = read_dir
635646
.filter_map(|r| {
636647
let e = match r {
@@ -654,47 +665,6 @@ impl FileSystem for DiskFileSystem {
654665
.collect::<Result<_>>()
655666
.with_context(|| format!("reading directory item in {}", full_path.display()))?;
656667

657-
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
658-
let mut read_dir = match tokio_fs_ext::read_dir(full_path.clone())
659-
.instrument(tracing::info_span!(
660-
"read dir",
661-
name = display(full_path.display())
662-
))
663-
.await
664-
{
665-
Ok(dir) => dir,
666-
Err(e)
667-
if e.kind() == ErrorKind::NotFound
668-
|| e.kind() == ErrorKind::NotADirectory
669-
|| e.kind() == ErrorKind::InvalidFilename =>
670-
{
671-
return Ok(RawDirectoryContent::not_found());
672-
}
673-
Err(e) => {
674-
bail!(anyhow!(e).context(format!("reading dir {}", full_path.display())))
675-
}
676-
};
677-
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
678-
let entries = {
679-
let mut entries = AutoMap::<RcStr, RawDirectoryEntry>::new();
680-
while let Some(e) = read_dir
681-
.next_entry()
682-
.await
683-
.with_context(|| format!("reading directory item in {}", full_path.display()))?
684-
{
685-
let file_name: RcStr = e.file_name().to_string_lossy().to_string().into();
686-
let entry = match e.file_type().await {
687-
Ok(t) if t.is_file() => RawDirectoryEntry::File,
688-
Ok(t) if t.is_dir() => RawDirectoryEntry::Directory,
689-
Ok(t) if t.is_symlink() => RawDirectoryEntry::Symlink,
690-
Ok(_) => RawDirectoryEntry::Other,
691-
Err(err) => return Err(err.into()),
692-
};
693-
entries.insert(file_name, entry);
694-
}
695-
entries
696-
};
697-
698668
Ok(RawDirectoryContent::new(entries))
699669
}
700670

@@ -720,15 +690,9 @@ impl FileSystem for DiskFileSystem {
720690
};
721691

722692
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
723-
let link_path = match tokio_fs_ext::read_link(full_path.clone())
724-
.instrument(tracing::info_span!(
725-
"read symlink",
726-
name = display(full_path.display())
727-
))
728-
.await
729-
{
730-
Ok(res) => res,
731-
Err(_) => return Ok(LinkContent::NotFound.cell()),
693+
let link_path: PathBuf = {
694+
// TODO: not supported now
695+
todo!()
732696
};
733697

734698
let is_link_absolute = link_path.is_absolute();
@@ -810,6 +774,7 @@ impl FileSystem for DiskFileSystem {
810774
let inner = self.inner.clone();
811775
let invalidator = turbo_tasks::get_invalidator();
812776

777+
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
813778
effect(async move {
814779
let full_path = validate_path_length(&full_path)?;
815780

@@ -862,7 +827,6 @@ impl FileSystem for DiskFileSystem {
862827

863828
let full_path_to_write = full_path.clone();
864829
let content = content.clone();
865-
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
866830
retry_blocking(full_path_to_write.into_owned(), move |full_path| {
867831
use std::io::Write;
868832

@@ -904,26 +868,8 @@ impl FileSystem for DiskFileSystem {
904868
))
905869
.await
906870
.with_context(|| format!("failed to write to {}", full_path.display()))?;
907-
908-
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
909-
if let FileContent::Content(file) = &*content {
910-
let mut content_buf = vec![];
911-
std::io::copy(&mut file.read(), &mut content_buf)?;
912-
tokio_fs_ext::write(full_path_to_write, content_buf)
913-
.instrument(tracing::info_span!(
914-
"write file",
915-
name = display(full_path.display())
916-
))
917-
.await
918-
.with_context(|| {
919-
format!("failed to write to {}", full_path.display())
920-
})?;
921-
} else {
922-
unreachable!()
923-
};
924871
}
925872
FileContent::NotFound => {
926-
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
927873
retry_blocking(full_path.clone().into_owned(), |path| {
928874
std::fs::remove_file(path)
929875
})
@@ -941,22 +887,6 @@ impl FileSystem for DiskFileSystem {
941887
}
942888
})
943889
.with_context(|| anyhow!("removing {} failed", full_path.display()))?;
944-
945-
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
946-
tokio_fs_ext::remove_file(full_path.clone())
947-
.instrument(tracing::info_span!(
948-
"remove file",
949-
name = display(full_path.display())
950-
))
951-
.await
952-
.or_else(|err| {
953-
if err.kind() == ErrorKind::NotFound {
954-
Ok(())
955-
} else {
956-
Err(err)
957-
}
958-
})
959-
.with_context(|| anyhow!("removing {} failed", full_path.display()))?;
960890
}
961891
}
962892

@@ -965,6 +895,30 @@ impl FileSystem for DiskFileSystem {
965895
Ok(())
966896
});
967897

898+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
899+
effect(async move {
900+
let full_path = validate_path_length(&full_path)?;
901+
902+
let _lock = inner.lock_path(&full_path).await;
903+
904+
if let FileContent::Content(file) = &*content {
905+
if let Some(create_directory) = full_path.parent() {
906+
wasm_fs_offload::CLIENT
907+
.create_dir_all(create_directory)
908+
.await?;
909+
}
910+
911+
let mut content_buf = vec![];
912+
std::io::copy(&mut file.read(), &mut content_buf)?;
913+
wasm_fs_offload::CLIENT
914+
.write(full_path, &content_buf)
915+
.await?;
916+
Ok(())
917+
} else {
918+
unreachable!()
919+
}
920+
});
921+
968922
Ok(())
969923
}
970924

@@ -1121,11 +1075,8 @@ impl FileSystem for DiskFileSystem {
11211075
.with_context(|| format!("reading metadata for {}", full_path.display()))?;
11221076

11231077
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
1124-
let meta = tokio_fs_ext::metadata(full_path.clone())
1125-
.instrument(tracing::info_span!(
1126-
"read metadata",
1127-
name = display(full_path.display())
1128-
))
1078+
let meta = wasm_fs_offload::CLIENT
1079+
.metadata(&full_path)
11291080
.await
11301081
.with_context(|| format!("reading metadata for {}", full_path.display()))?;
11311082
Ok(FileMeta::cell(meta.into()))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use std::sync::LazyLock;
2+
3+
use anyhow::{Context, Result};
4+
use parking_lot::Mutex;
5+
use tokio::sync::oneshot;
6+
use tokio_fs_ext::offload::{self, FsOffload};
7+
8+
static WASM_FS_OFFLOAD: LazyLock<(Mutex<offload::Server>, offload::Client)> = LazyLock::new(|| {
9+
let (server, client) = offload::split();
10+
(Mutex::new(server), client)
11+
});
12+
13+
pub static CLIENT: LazyLock<offload::Client> = LazyLock::new(|| WASM_FS_OFFLOAD.1.clone());
14+
15+
pub async fn server(offload: impl FsOffload) {
16+
WASM_FS_OFFLOAD.0.lock().serve(offload).await
17+
}

0 commit comments

Comments
 (0)