Skip to content

Commit 2922caf

Browse files
committed
Enable union types without interfaces in WebIDL
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 #817
1 parent a2d6a8f commit 2922caf

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

crates/web-sys/webidls/enabled/FormData.webidl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ interface FormData {
1717
[Throws]
1818
void append(USVString name, USVString value);
1919
void delete(USVString name);
20-
FormDataEntryValue? get(USVString name);
20+
// FIXME: this is a wasm-bindgen specific modification. We currently translate
21+
// the `FormDataEntryValue` to `JsValue`, but the `?` here means this returns
22+
// `Option<JsValue>`, which isn't implemented. We hack around that and force
23+
// it to use `any`, and it's up to callers to figure out what to do.
24+
// FormDataEntryValue? get(USVString name);
25+
any get(USVString name);
2126
sequence<FormDataEntryValue> getAll(USVString name);
2227
boolean has(USVString name);
2328
[Throws]

crates/webidl/src/idl_type.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -527,13 +527,29 @@ impl<'a> IdlType<'a> {
527527
IdlType::Promise(_idl_type) => js_sys("Promise"),
528528
IdlType::Record(_idl_type_from, _idl_type_to) => None,
529529
IdlType::Union(idl_types) => {
530-
// Handles union types in all places except operation argument types.
531-
// Currently treats them as object type, if possible.
532-
// TODO: add better support for union types here?
533-
// Approaches for it:
534-
// 1. Use strategy of finding the nearest common subclass (finding the best type
535-
// that is suitable for all values of this union)
536-
// 2. Generate enum with payload in Rust for each union type
530+
// Note that most union types have already been expanded to
531+
// their components via `flatten`. Unions in a return position
532+
// or dictionary fields, however, haven't been flattened, which
533+
// means we may need to conver them to a `syn` type.
534+
//
535+
// Currently this does a bit of a "poor man's" tree traversal by
536+
// saying that if all union members are interfaces we can assume
537+
// they've all got `Object` as a superclass, so we can take an
538+
// object here. If any are not an interface though we
539+
// pessimisitcally translate the union into a `JsValue`,
540+
// absolutely anything. It's up to the application to figure out
541+
// what to do with that.
542+
//
543+
// TODO: we should probably do a better job here translating
544+
// unions to a single type. Two possible strategies could be:
545+
//
546+
// 1. Use strategy of finding the nearest common subclass
547+
// (finding the best type that is suitable for all values of
548+
// this union) instead of always assuming `Object`.
549+
// 2. Generate enum with payload in Rust for each union type.
550+
// Such an enum, however, might have a relatively high
551+
// overhead in creating it from a JS value, but would be
552+
// cheap to convert from a variant back to a JS value.
537553
if idl_types
538554
.iter()
539555
.all(|idl_type|
@@ -544,7 +560,7 @@ impl<'a> IdlType<'a> {
544560
) {
545561
IdlType::Object.to_syn_type(pos)
546562
} else {
547-
None
563+
IdlType::Any.to_syn_type(pos)
548564
}
549565
},
550566

0 commit comments

Comments
 (0)