stdweb icon indicating copy to clipboard operation
stdweb copied to clipboard

Leverage WebIDL to generate API wrappers

Open casey opened this issue 7 years ago • 13 comments

Not sure this is already on your radar, but as webassembly moves forward it might be worth looking at autogenerating rust interfaces based on WebIDL specs:

https://github.com/heycam/webidl

This document contains some interesting notes about IDL + WebAssembly

https://github.com/WebAssembly/design/blob/master/GC.md

Even if the generated rust code isn't particularly idiomatic, it could take care of a lot of tedious FFI work.

casey avatar Apr 26 '17 05:04 casey

This is definitely something I'd like to look into in the future!

Ideally I'd probably envision something like this: * We autogenerate the vast majority of the API automatically from WebIDL; we keep it private. (Or perhaps have an stdweb-sys crate or something like that; it's hard to tell right now.) * We reexport parts which feel like idiomatic Rust. * We write very thin wrappers around parts which are not idiomatic (e.g. removeEventListener).

Right now though I think it's still too early for this, especially since neither webasm is ready for this nor I (we?) haven't fully explored yet what are the tradeoffs when interacting with JavaScript from Rust and in general what's the best way to do it.

koute avatar Apr 26 '17 17:04 koute

I think you're correct about the not-yet-ready part. I've only seen a few tiny examples of Rust / webasm FFI so far, which are mostly hand rolled.

One thing which would help enormously in this effort would be a central repository of WebIDL APIs. It seems that most WebIDL only exists in specs.

casey avatar Apr 27 '17 03:04 casey

Ooooo, jackpot! Looks like there is a directory full of WebIDL files for the browser APIs in the firefox source tree:

https://dxr.mozilla.org/mozilla-central/source/dom/webidl

I'm not sure if these are used directly, or are perhaps simply a reference.

casey avatar Apr 28 '17 04:04 casey

Web DOM IDL files and support files copied from Blink : https://github.com/dart-lang/webcore

ghost avatar May 24 '17 11:05 ghost

Thanks for the links; it'll certainly come in handy once I get to it, although it'll probably take quite a while until I do. (Unless someone else would like to take a stab at this; I guess writing a parser in Rust for the .idl files would be a good first step [so we can generate whatever we need to generate from these in a build.rs].)

koute avatar May 24 '17 20:05 koute

Servo does some webidl parsing and rust code gen:

https://github.com/servo/servo/tree/master/components/script/dom/bindings/codegen

LegNeato avatar Jul 06 '17 15:07 LegNeato

I've been playing with this a tiny bit. The webidl crate can successfully parse thorugh all of these IDLs from servo. The Mozilla and Chromium IDLs both use non-standard extensions to the grammar that webidl-rs doesn't support. I've got it parsing in a build.rs, but not really doing much code generation yet.

My first instinct is that generating these in a stdweb-sys submodule/crate is the way to go, as I expect we'll want to re-implement most of the APIs on top of the sys versions. For example, a lot of the JS 'enum'-ish APIs aren't listed as enums in the IDL, and we'd have to manually map these to a Rust enum type, unless we can put this info in the IDL in some way.

(I can't believe that W3C or WHATWG don't just provide a repo of standard IDLs somewhere?!)

Herschel avatar Oct 17 '17 19:10 Herschel

I implemented a fairly powerful WebIDL => stdweb binding generator: https://github.com/brendanzab/gl-rs/pull/447

It is specifically for WebGL at the moment, although I don't imagine it would require too many changes to use with other APIs.

It is able to fully understand WebIDL types and map them onto the best rust interface, taking into account that parameters are typically passed by reference vs return values by move, and it's capable of remapping types, performing custom conversions for specific types, and annotating methods with generic parameters and constraints to allow for more usable APIs.

As an example, it can take these IDL definitions:

typedef unsigned long  GLuint;
typedef ([AllowShared] Float32Array or sequence<GLfloat>) Float32List;
...
void vertexAttrib4fv(GLuint index, Float32List values);

And convert them to this:

pub type GLuint = u32;
pub type Float32List = TypedArray<f32>;
...
pub fn vertex_attrib4fv<'a0, T0>(&self, index: u32, values: T0) where T0: AsTypedArray<'a0, f32> {
    js!( @{self}.vertexAttrib4fv(@{index}, @{unsafe { values.as_typed_array() }}); );
}

Diggsey avatar Jan 28 '18 17:01 Diggsey

There is also https://github.com/kryptan/webinden by @kryptan

LegNeato avatar Jan 29 '18 01:01 LegNeato

@Diggsey Does this also work for callback based APIs like Geolocation? https://w3c.github.io/geolocation-api/#idl-index (I really want Geolocation in stdweb/yew..)

Btw, here is how the FFI for the Geolocation API is defined in PureScript: https://github.com/chexxor/purescript-dom-geolocation/blob/use-aff/src/DOM/HTML/Navigator/Geolocation.purs https://github.com/chexxor/purescript-dom-geolocation/blob/use-aff/src/DOM/HTML/Navigator/Geolocation.js

Boscop avatar Aug 14 '18 14:08 Boscop

@Boscop not sure until you try it.

Diggsey avatar Aug 14 '18 14:08 Diggsey

@Diggsey Is your Web IDL bindings generator available in its own crate somewhere?

Boscop avatar Aug 14 '18 17:08 Boscop

No, it's just everything in this module right now: https://github.com/brendanzab/gl-rs/tree/master/webgl_generator/webgl_registry

Diggsey avatar Aug 14 '18 17:08 Diggsey