Add support for optional slice types (#507)

* Shard the `convert.rs` module into sub-modules

Hopefully this'll make the organization a little nicer over time!

* Start adding support for optional types

This commit starts adding support for optional types to wasm-bindgen as
arguments/return values to functions. The strategy here is to add two new
traits, `OptionIntoWasmAbi` and `OptionFromWasmAbi`. These two traits are used
as a blanket impl to implement `IntoWasmAbi` and `FromWasmAbi` for `Option<T>`.

Some consequences of this design:

* It should be possible to ensure `Option<SomeForeignType>` implements to/from
  wasm traits. This is because the option-based traits can be implemented for
  foreign types.
* A specialized implementation is possible for all types, so there's no need for
  `Option<T>` to introduce unnecessary overhead.
* Two new traits is a bit unforutnate but I can't currently think of an
  alternative design that works for the above two constraints, although it
  doesn't mean one doesn't exist!
* The error messages for "can't use this type here" is actually halfway decent
  because it says these new traits need to be implemented, which provides a good
  place to document and talk about what's going on here!
* Nested references like `Option<&T>` can't implement `FromWasmAbi`. This means
  that you can't define a function in Rust which takes `Option<&str>`. It may be
  possible to do this one day but it'll likely require more trait trickery than
  I'm capable of right now.

* Add support for optional slices

This commit adds support for optional slice types, things like strings and
arrays. The null representation of these has a pointer value of 0, which should
never happen in normal Rust. Otherwise the various plumbing is done throughout
the tooling to enable these types in all locations.

* Fix `takeObject` on global sentinels

These don't have a reference count as they're always expected to work, so avoid
actually dropping a reference on them.

* Remove some no longer needed bindings

* Add support for optional anyref types

This commit adds support for optional imported class types. Each type imported
with `#[wasm_bindgen]` automatically implements the relevant traits and now
supports `Option<Foo>` in various argument/return positions.

* Fix building without the `std` feature

* Actually fix the build...

* Add support for optional types to WebIDL

Closes #502
This commit is contained in:
Alex Crichton
2018-07-19 14:44:23 -05:00
committed by GitHub
parent 6eef5f7b52
commit cbeb301371
20 changed files with 1214 additions and 725 deletions

View File

@ -125,10 +125,6 @@ impl<'a> FirstPassRecord<'a> {
ty: &webidl::ast::Type,
pos: TypePosition,
) -> Option<syn::Type> {
// nullable types are not yet supported (see issue #14)
if ty.nullable {
return None;
}
let array = |base_ty: &str| {
match pos {
TypePosition::Argument => {
@ -140,7 +136,7 @@ impl<'a> FirstPassRecord<'a> {
}
};
Some(match ty.kind {
let base_ty = match ty.kind {
// `any` becomes `::wasm_bindgen::JsValue`.
webidl::ast::TypeKind::Any => {
simple_path_ty(vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")])
@ -223,7 +219,25 @@ impl<'a> FirstPassRecord<'a> {
| webidl::ast::TypeKind::Union(_) => {
return None;
}
})
};
if ty.nullable {
let arguments = syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: FromIterator::from_iter(vec![
syn::GenericArgument::Type(base_ty),
]),
gt_token: Default::default(),
});
let ident = raw_ident("Option");
let seg = syn::PathSegment { ident, arguments };
let path: syn::Path = seg.into();
let ty = syn::TypePath { qself: None, path };
Some(ty.into())
} else {
Some(base_ty)
}
}
fn webidl_arguments_to_syn_arg_captured<'b, I>(