Skip to content
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 webidl iterable support #3962

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

RaoulHC
Copy link

@RaoulHC RaoulHC commented May 15, 2024

Was trying to figure out how to list files in OPFS before I realised these methods were just missing from web-sys.

Added some tests that use these and more generally test some of the file system API, only tested it with geckodriver but it should be well supported across all browsers.

Also added some flags so that the optional stream module should get generated in docs.rs too, wasn't obvious it existed, and it's somewhat needed to make use of the AsyncIterator that these methods return.

@RaoulHC
Copy link
Author

RaoulHC commented May 16, 2024

Oh I see I missed that the web-sys files are generated from webidl, and that the async iterable field is what should be providing the entries/keys/values methods. Given the following code am I right in thinking this isn't currently supported?

InterfaceMember::AsyncIterable(_iterable) => {
log::warn!(
"Unsupported WebIDL async iterable interface member: {:?}",
self
);
Ok(())
}

@Liamolucko
Copy link
Collaborator

Given the following code am I right in thinking this isn't currently supported?

InterfaceMember::AsyncIterable(_iterable) => {
log::warn!(
"Unsupported WebIDL async iterable interface member: {:?}",
self
);
Ok(())
}

Yes; there's an old issue #514 about it.

@RaoulHC
Copy link
Author

RaoulHC commented May 16, 2024

Yes; there's an old issue #514 about it.

Yep found that and am getting something working, looks like it's relatively simple to add, most of the plumbing is already there, so will update this PR.

Use the doc_cfg feature to show it's behind futures-core-03-stream
feature flag.
@RaoulHC RaoulHC force-pushed the raoul/missing-directory-methods branch from e5a2793 to 6cc1be2 Compare May 16, 2024 08:56
Most of the plumbing was there but now (async) iterable instances
generate the `entries`, `keys` and `values` methods. `forEach` is also
generated for the non-async iterable.
@RaoulHC RaoulHC force-pushed the raoul/missing-directory-methods branch from 6cc1be2 to 6047da3 Compare May 16, 2024 08:58
@RaoulHC RaoulHC changed the title Add missing FileSystemDirectoryHandle methods Add webidl iterable support May 16, 2024
@RaoulHC
Copy link
Author

RaoulHC commented May 16, 2024

I've got something working that I've pushed, wasn't sure how to do the async forEach method so I've left that for now, I think most users will probably want to use the futures Stream interface via JsStream anyway.

Looking at how the ergonomics could be improved given we know the types yielded for these cases, some ideas in that issue so will see if something can work.

@RaoulHC
Copy link
Author

RaoulHC commented May 17, 2024

Playing around with it a bit, I think the neatest way might be leave the exposed js methods (maybe prepend with a js_?) but also generate a shim that uses the type information to give a generate an (async) iterator that uses unchecked_into to massage it into something nicer to deal with in rust.

So for FileSystemDirectoryHandle it'd be something like this:

impl FileSystemDirectoryHandle
   pub fn entries() -> impl Stream<Item = (JsString, FileSystemHandle)> {
       JsStream::from(self.js_entries()).map(|x| {
            let array = x.unwrap().unchecked_into::<Array>();
            (array.at(0).unchecked_into(), array.at(1).unchecked_into())
        })
    }
}

with something similar for regular iterables, and without the array step for keys and values, which only return the one item.

Thoughts? It seems like there was a bunch of discussions regarding iterators but the direction was never really settled and a lot of those main contributors are no longer on wasm-bindgen, Probably need to read a bit more into if there are ever any cases where iterables for some of these methods can throw errors, but hand writing this for the directory case works fairly nicely with the tests I have.

@RaoulHC
Copy link
Author

RaoulHC commented May 21, 2024

I've had a bit of a crack at this, but how you massage the types was trickier than I thought, Web IDL has types that JS doesn't so to cast to equivalent rust types you have to go via js types which doesn't always cast simply. Some API's generate enums that I also wasn't sure exactly how to deal with (see MediaKeyStatus in MediaKeyStatusMap. There's also the question of whether we want to stick to Js values (i.e. JsString and js_sys::Number) or convert to rust values closer to what Web IDL specifies: sticking to js values means there wont be unnecessary copies, but you lose some of the type information specified for the API.

I think for now exposing these methods that just return js iterators allows users to at least use the iterable interfaces, they'll just have to deal with casting to the types they want. Maybe we want to gate it behind a feature flag if we plan on changing the API later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants