Skip to content

Commit

Permalink
Enable union types without interfaces in WebIDL
Browse files Browse the repository at this point in the history
Bind them all as `JsValue` as that's the "least common ancestor" we can
work with. Fixes up one location in WebIDL where `Option<JsValue>`
arose as we haven't implemented that.

Closes rustwasm#817
  • Loading branch information
alexcrichton committed Sep 21, 2018
1 parent a2d6a8f commit 2922caf
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
7 changes: 6 additions & 1 deletion crates/web-sys/webidls/enabled/FormData.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ interface FormData {
[Throws]
void append(USVString name, USVString value);
void delete(USVString name);
FormDataEntryValue? get(USVString name);
// FIXME: this is a wasm-bindgen specific modification. We currently translate
// the `FormDataEntryValue` to `JsValue`, but the `?` here means this returns
// `Option<JsValue>`, which isn't implemented. We hack around that and force
// it to use `any`, and it's up to callers to figure out what to do.
// FormDataEntryValue? get(USVString name);
any get(USVString name);
sequence<FormDataEntryValue> getAll(USVString name);
boolean has(USVString name);
[Throws]
Expand Down
32 changes: 24 additions & 8 deletions crates/webidl/src/idl_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,13 +527,29 @@ impl<'a> IdlType<'a> {
IdlType::Promise(_idl_type) => js_sys("Promise"),
IdlType::Record(_idl_type_from, _idl_type_to) => None,
IdlType::Union(idl_types) => {
// Handles union types in all places except operation argument types.
// Currently treats them as object type, if possible.
// TODO: add better support for union types here?
// Approaches for it:
// 1. Use strategy of finding the nearest common subclass (finding the best type
// that is suitable for all values of this union)
// 2. Generate enum with payload in Rust for each union type
// Note that most union types have already been expanded to
// their components via `flatten`. Unions in a return position
// or dictionary fields, however, haven't been flattened, which
// means we may need to conver them to a `syn` type.
//
// Currently this does a bit of a "poor man's" tree traversal by
// saying that if all union members are interfaces we can assume
// they've all got `Object` as a superclass, so we can take an
// object here. If any are not an interface though we
// pessimisitcally translate the union into a `JsValue`,
// absolutely anything. It's up to the application to figure out
// what to do with that.
//
// TODO: we should probably do a better job here translating
// unions to a single type. Two possible strategies could be:
//
// 1. Use strategy of finding the nearest common subclass
// (finding the best type that is suitable for all values of
// this union) instead of always assuming `Object`.
// 2. Generate enum with payload in Rust for each union type.
// Such an enum, however, might have a relatively high
// overhead in creating it from a JS value, but would be
// cheap to convert from a variant back to a JS value.
if idl_types
.iter()
.all(|idl_type|
Expand All @@ -544,7 +560,7 @@ impl<'a> IdlType<'a> {
) {
IdlType::Object.to_syn_type(pos)
} else {
None
IdlType::Any.to_syn_type(pos)
}
},

Expand Down

0 comments on commit 2922caf

Please sign in to comment.