Missing WebIDL processing features overview
MOZGIII opened this issue · comments
I was doing a manual implementation for the WebTransport types, and here's case-study-based a list of missing features that makes WebIDL codegen really unusable:
- Lack of getters support for dictionaries. A lot of dictionaries are used in return positions:
ReadableStream
, pretty much everywhere in thegetStats
for WebTransport, etc. - Dictionaries setters do not allow unsetting values (for the most part) - we might want to either make them all take
Option<T>
instead ofT
, or generate an additional accessor to allowunset_...
. - Untyped async calls - the WebIDL has enough data to properly deduce the type, but that is not done, and an untype
js_sys::Promise
it returned instead. We should consider adding types support to thejs_sys::Promise
, and also generating the calls that return promises as realasync fn
s. This is, however, blocked by #3919, asasync
fn generation is broken. - Well, #3919. The
async
fn generation is broken. - The
catch
is not generated correctly. This is an issue with WebIDL definitions, as they lack the machine-readable data on whether a call can throw or not - but nonetheless I count this towards the list of issues of the WebIDL-generated rust code. ReadableStream
/WriteableStream
should have a generic indicating what type they produce - they are capable of streaming not just the bytes (i.e. binary data, where they act like Read/Write), but objects too (acting more like a stream / async iterator in rust sense).- Inability to turn certain hot calls
final
at the codegen level. - I can't just install the latest
wasm_bindgen_webidl
as a dependency and use it in my crate - as the latest version is not published, and the last published is very old and conflicts with the rest of the crates. This is by far the easiest issue to solve. - Errors types are not properly indicated anywhere, while the WebIDL has relevant info.
Also, some nits I encountered while implementing things manually.
missing_docs
lint is triggered forwasm_bindgen
macro enums.- No explicit support for attributes as
wasm_bindgen
macro, as in syntax sugar for generating both getter and setter from the same attribute. - Declaring dictionaries manually is too verbose, they should really be a first-class item in the macro.
Not sure this is the right place for this, and those issue are most definitely reported before - but this is a case study organized in one place, and will hopefully act like a concise roadmap towards a better support for WebIDL. Hopefully if all those are solved somehow we'd get a way nicer codegen.
For now, using WebIDL is much more painful than using custom type declarations.
Dictionaries setters do not allow unsetting values (for the most part) - we might want to either make them all take
Option<T>
instead ofT
, or generate an additional accessor to allowunset_...
.
Just a quick comment on this one: allowing to unset values would effectively void the conditions that should hold for reading the properties. Meaning that all getters would need to be wrapped in an Option
.
I guess you could implement the unset_...
functions anyway and mark them unsafe
?
Not all of them - the attribute
?
(with ?
at the end) - ones only, those should be unsettable, as they can effectively be not set and read as null
(as I understand - null
specifically, not undefined
). For those values we absolutely need getters to return Option
.
UPD: oh, yeah, dictionaries, right. They don't have definitions like that, and thus must absolutely always do the explicit Option<T>
for all values. In my opinion, it is not about the ergonomics - but about correctness. In the context of a dictionaries, WebIDL does not actually encode the expected default values - so we can't procedurally generate them - but the spec itself usually does, so it is possible for a developer to properly deduce what value will be in effect if a dictionary value is unset, on a case-by-case basis via reading the docs. Combined with limitations of panics at wasm, and this becomes the only solution to avoid super-fragile apps imo.
In the context of a dictionaries, WebIDL does not actually encode the expected default values
They actually do, so I think your suggestion of allowing to unset optional values only would work great.
E.g. the first dictionary declaration I could find going alphabetically in the enabled WebIDLs:
wasm-bindgen/crates/web-sys/webidls/enabled/AnalyserNode.webidl
Lines 13 to 18 in e78db23
It just looks like the code generation for dictionary constructors produces undefined behavior by not setting default values in new
:
wasm-bindgen/crates/web-sys/src/features/gen_AnalyserOptions.rs
Lines 30 to 38 in e78db23
I'll open a separate issue for that.