Skip to content

Commit

Permalink
fix: drop file handle after closing
Browse files Browse the repository at this point in the history
  • Loading branch information
crwen committed Feb 5, 2025
1 parent 00371dd commit 6f2b12b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
31 changes: 23 additions & 8 deletions fusio/src/impls/disk/opfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ where

/// OPFS based on [FileSystemWritableFileStream](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream)
pub struct OPFSFile {
file_handle: FileSystemFileHandle,
file_handle: Option<FileSystemFileHandle>,
write_stream: Option<FileSystemWritableFileStream>,
pos: u64,
}
Expand Down Expand Up @@ -60,14 +60,16 @@ impl OPFSFile {
};

Ok(Self {
file_handle,
file_handle: Some(file_handle),
write_stream,
pos: size.round() as u64,
})
}

async fn reader(&self, pos: u64, buf_len: u64) -> Result<ReadableStreamDefaultReader, Error> {
let file = promise::<File>(self.file_handle.get_file()).await?;
debug_assert!(self.file_handle.is_some());
let file_handle = self.file_handle.as_ref().expect("read file after closed.");
let file = promise::<File>(file_handle.get_file()).await?;

if (file.size().round() as u64) < pos + buf_len as u64 {
return Err(Error::Io(io::Error::new(
Expand All @@ -76,7 +78,12 @@ impl OPFSFile {
)));
}

let blob = file.slice_with_i32(pos as i32).unwrap();
let blob = if buf_len == 0 {
file.slice_with_i32(pos as i32).unwrap()
} else {
file.slice_with_i32_and_i32(pos as i32, (pos + buf_len) as i32)
.unwrap()
};
blob.stream()
.get_reader()
.dyn_into::<ReadableStreamDefaultReader>()
Expand All @@ -97,7 +104,7 @@ impl Write for OPFSFile {
match JsFuture::from(
self.write_stream
.as_ref()
.unwrap()
.expect("write file after closed.")
.write_with_u8_array(buf.as_slice())
.unwrap(),
)
Expand All @@ -114,8 +121,8 @@ impl Write for OPFSFile {

/// Close the associated OPFS file.
async fn close(&mut self) -> Result<(), Error> {
let writer = self.write_stream.take();
if let Some(writer) = writer {
let _ = self.file_handle.take();
if let Some(writer) = self.write_stream.take() {
JsFuture::from(writer.close()).await.map_err(wasm_err)?;
}
Ok(())
Expand Down Expand Up @@ -180,7 +187,15 @@ impl Read for OPFSFile {

/// Return the size of file in bytes.
async fn size(&self) -> Result<u64, Error> {
let file = promise::<File>(self.file_handle.get_file()).await?;
debug_assert!(self.file_handle.is_some());

let file = promise::<File>(
self.file_handle
.as_ref()
.expect("read file after closed.")
.get_file(),
)
.await?;

Ok(file.size() as u64)
}
Expand Down
27 changes: 18 additions & 9 deletions fusio/tests/opfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ pub(crate) mod tests {
async fn test_opfs_read_write() {
let fs = OPFS;
let mut file = fs
.open_options(&"file_rw".into(), OpenOptions::default().create(true).truncate(true))
.open_options(
&"file".into(),
OpenOptions::default().create(true).truncate(true),
)
.await
.unwrap();
let (result, _) = file.write_all([1, 2, 3, 4].as_mut()).await;
Expand All @@ -102,7 +105,7 @@ pub(crate) mod tests {
file.close().await.unwrap();

let mut file = fs
.open_options(&"file_rw".into(), OpenOptions::default().create(true))
.open_options(&"file".into(), OpenOptions::default())
.await
.unwrap();
let expected = [1_u8, 2, 3, 4, 11, 23, 34, 47, 121, 93, 94, 97];
Expand All @@ -116,14 +119,17 @@ pub(crate) mod tests {
let (result, data) = file.read_exact_at(buf.as_mut(), 3).await;
result.unwrap();
assert_eq!(data, [4, 11, 23, 34, 47, 121, 93]);
remove_all(&fs, &["file_rw"]).await;
remove_all(&fs, &["file"]).await;
}

#[wasm_bindgen_test]
async fn test_opfs_read_write_utf16() {
let fs = OPFS;
let mut file = fs
.open_options(&"file_utf16".into(), OpenOptions::default().create(true).truncate(true))
.open_options(
&"file".into(),
OpenOptions::default().create(true).truncate(true),
)
.await
.unwrap();
let utf16_bytes: &[u8] = &[
Expand All @@ -136,7 +142,7 @@ pub(crate) mod tests {
file.close().await.unwrap();

let mut file = fs
.open_options(&"file_utf16".into(), OpenOptions::default().write(true))
.open_options(&"file".into(), OpenOptions::default())
.await
.unwrap();
let (result, data) = file.read_to_end_at(vec![], 0).await;
Expand All @@ -149,14 +155,17 @@ pub(crate) mod tests {
]
);

remove_all(&fs, &["file_utf16"]).await;
remove_all(&fs, &["file"]).await;
}

#[wasm_bindgen_test]
async fn test_opfs_read_eof() {
let fs = OPFS;
let mut file = fs
.open_options(&"file_eof".into(), OpenOptions::default().create(true).truncate(true))
.open_options(
&"file".into(),
OpenOptions::default().create(true).truncate(true),
)
.await
.unwrap();

Expand All @@ -169,14 +178,14 @@ pub(crate) mod tests {
file.close().await.unwrap();

let mut file = fs
.open_options(&"file_eof".into(), OpenOptions::default().write(true))
.open_options(&"file".into(), OpenOptions::default())
.await
.unwrap();

let mut buf = [0; 1];
let (result, data) = file.read_exact_at(buf.as_mut(), 5).await;
assert!(result.is_err());
assert_eq!(data, [0]);
remove_all(&fs, &["file_eof"]).await;
remove_all(&fs, &["file"]).await;
}
}

0 comments on commit 6f2b12b

Please sign in to comment.