-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for FileSystemSyncAccessHandle in OPFS #34
Conversation
|
Thanks a lot for working on this!
Weird that it is never closed. Can you use the strace wrapper to show all syscalls that are made? In any case there should be code added to handle opening the same file multiple times. At least once directories are supported. |
src/fs_fd.ts
Outdated
@@ -178,6 +262,8 @@ export class OpenDirectory extends Fd { | |||
if (entry instanceof File) { | |||
// @ts-ignore | |||
return { ret: 0, fd_obj: new OpenFile(entry) }; | |||
} else if (entry instanceof OPFSFile) { | |||
return { ret: 0, fd_obj: new OpenOPFSFile(entry) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe these cases should all be replaced with an open()
method on a new DirEntry
or Inode
base class which File
, SyncOPFSFile
and Directory
would then derive from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't they all already derive from Fd
? We could just use duck-typing to check if the entry
has an open()
property and call that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, none of File | SyncOPFSFile | Directory
derived from Fd
but Typescript handles the type union to check if .open()
exists just fine without a common base class: 512a46d
Maybe I should clarify: by opening a second time I mean starting a second WebAssembly instance, which also tries to open the file from OPFS. So technically, the previous instance simply still holds the lock on the file. My expectation would have been that at the end of Anyway, how do I use the strace wrapper? Just wrap the
|
For reactor style wasi modules as handled by
Yes: browser_wasi_shim/examples/rustc.html Lines 129 to 131 in ee4f287
|
Aha! Mea culpa .. the Rust experiment actually does close the file as seen here: This is the code that is executed there: fn main() {
println!("This is Rust.");
// print commandline arguments
let args: Vec<String> = std::env::args().collect();
let name = args[0].clone();
println!("file '{name}' was called with arguments: {args:?}");
// print environment variables
println!("environment variables:");
for (key, value) in std::env::vars() {
println!(" - {}: {}", key, value);
};
// list root filesystem
match std::fs::read_dir("/") {
Err(e) => println!("ERR: couldn't open directory '/': {e}"),
Ok(iter) => {
println!("listing '/' contents:");
for item in iter {
println!(" - {}", item.unwrap().path().display());
}
}
};
// try to read a specific file
const FILENAME: &str = "/hello.txt";
match std::fs::read(FILENAME) {
Err(e) => println!("ERR: couldn't open file '{FILENAME}': {e}"),
Ok(content) => {
let text = String::from_utf8_lossy(&content);
println!("'{FILENAME}': {text}");
},
}
} My TinyGo experiment however, does not .. package main
import (
"fmt"
"io"
"os"
)
func main() {
fmt.Println("This is TinyGo.")
// print commandline arguments
args := os.Args
name := args[0]
fmt.Printf("file '%s' was called with arguments: %v\n", name, args)
// print environment variables
fmt.Println("environment variables:")
for _, env := range os.Environ() {
fmt.Printf(" - %s\n", env)
}
// list root filesystem
contents, err := os.ReadDir("/")
if err != nil {
fmt.Printf("ERR: couldn't open directory '/': %s\n", err)
} else {
fmt.Println("listing '/' contents:")
for _, item := range contents {
fmt.Printf(" - %s\n", item.Name())
}
}
// try to read a specific file
const FILENAME = "/hello.txt"
file, err := os.Open(FILENAME)
if err != nil {
fmt.Printf("ERR: couldn't open file '%s': %s\n", FILENAME, err)
} else {
bytes, err := io.ReadAll(file)
if err != nil {
fmt.Printf("ERR: couldn't read file '%s': %s\n", FILENAME, err)
} else {
fmt.Printf("'%s': %s\n", FILENAME, string(bytes))
}
}
} I mean, yeah .. I neither call nor defer |
It is definitely incorrect to close the handle in |
and remove the console.log lines
I've tested writes and caught an OOB bug in the process; added support for Regarding the closing of the The If you don't have any further comments, I think you might merge this now as the basic read / write / seek / append operations work now, as far as I can tell. |
I'm going to test this myself tomorrow. If I don't see anything weird I will merge it. |
@@ -174,15 +255,7 @@ export class OpenDirectory extends Fd { | |||
// @ts-ignore | |||
entry.truncate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bjorn3 Now that I've added fd_flags
to entry.open()
below, maybe the truncate call should also be moved to the File | SyncOPFSFile
constructors?
Got it working locally. |
Do you have more changes you want or shall I publish a new release with this? |
Great! 😊
Right now I'm just glad you found this useful enough to merge so quickly. :) I see you reopened the issue to track work on the async API / whole directories .. that'd be great but I don't think I can justify the effort to even attempt that right now. It probably should've been part of this PR but maybe add another usage example on how to use this new Other than that I don't have anything that should be a blocker for a new release, I think. |
No problem.
The code I used to test it was using the OPFS file as stderr for rustc.wasm and then manually verifying that it wrote to the file in the browser console. Not really something usable as test for others. |
This could partly fix #32 by allowing to use
FileSystemSyncAccessHandle
s in Workers for single files opened from OPFS as noted in my last comment. Usage example:This should currently be considered very WIP, as I've developed this out-of-tree in my project and then tried to copy it into this fork. That means I haven't actually run the code here yet.In my project I could successfully read a small file though: