Given a js_sys::Object, how do you call one of its functions?
Specifically I get a webgl extension via https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.WebGlRenderingContext.html#method.get_extension
After extracting the inner object, I want to call its functions from Rust (e.g. https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays#Methods)
How do I do this? :)
@dakom You can use Reflect::get to access the members and then Reflect::apply to call them.
But that's pretty terrible (and slow), so a much better approach is to create some bindings for it:
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = ANGLEInstancedArrays)]
type AngleInstancedArrays;
#[wasm_bindgen(method, getter, js_name = VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)]
fn vertex_attrib_array_divisor_angle(this: &AngleInstancedArrays) -> i32;
#[wasm_bindgen(method, catch, js_name = drawArraysInstancedANGLE)]
fn draw_arrays_instanced_angle(this: &AngleInstancedArrays, mode: u32, first: i32, count: i32, primcount: i32) -> Result<(), JsValue>;
// TODO offset should be i64
#[wasm_bindgen(method, catch, js_name = drawElementsInstancedANGLE)]
fn draw_elements_instanced_angle(this: &AngleInstancedArrays, mode: u32, count: i32, type_: u32, offset: i32, primcount: i32) -> Result<(), JsValue>;
#[wasm_bindgen(method, js_name = vertexAttribDivisorANGLE)]
fn vertex_attrib_divisor_angle(this: &AngleInstancedArrays, index: u32, divisor: u32);
}
Then you can convert your Object into an AngleInstancedArrays by using this:
let foo = foo.unchecked_into::<AngleInstancedArrays>();
@alexcrichton @fitzgen Can we somehow auto-generate bindings for the WebGL extensions? There is IDL for it.
I think this is a duplicate of https://github.com/rustwasm/wasm-bindgen/issues/1257, so I'm going to close in favor of that (but cc @Pauan's excellent answer over there) and the general problem for supporting this is tracked at https://github.com/rustwasm/wasm-bindgen/issues/893 which I think https://github.com/rustwasm/wasm-bindgen/pull/1405 may help start paving the path towards implementing.
[wasm_bindgen(js_name = ANGLEInstancedArrays)]
type AngleInstancedArrays;
@Pauan Can you please explain a little more what's going on there?
The section from The Rust Book that talks about type aliases doesn't seem to mention creating a type alias to nothing...
e.g. all the examples there have type foo = bar and I'm not clear on what's happening with just type foo
Sorry for another newbie question... and I realize this might not be specific to wasm-bindgen, but I'm thinking maybe the annotation above it is doing some magic?
@dakom It's not a type alias, it's an extern type (it's inside of an extern block).
It's something specific to the wasm-bindgen macro, you can't use it outside of wasm-bindgen (there is experimental support for it in Rust itself, but it's used for C, not JS).
It basically says "create a new type in Rust, but it's actually a JS type, so internally it just uses JsValue".
It's basically just used to wrap JS types into statically type safe Rust types.
So in the above code, type AngleInstancedArrays; will get translated into something like struct AngleInstancedArrays(JsValue), except with some additional wasm-bindgen stuff.
@Pauan I just wanted to thank you for the above information... Using your documentation I was able to achieve the following (maybe this helps someone else)...
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = EXT_texture_filter_anisotropic)]
type ExtTextureFilterAnisotropic;
}
let mut extension = ctx.gl.get_extension("EXT_texture_filter_anisotropic").unwrap().unwrap()
.unchecked_into::<ExtTextureFilterAnisotropic>();
let property = JsValue::from_str("MAX_TEXTURE_MAX_ANISOTROPY_EXT");
let value = js_sys::Reflect::get(&extension, &property);
console::log_1(&extension);
console::log_1(&property);
console::log_1(&value.unwrap());

@alexcrichton The team has done a tremendous job of the WASM bind-gen and in a very short period of time. I looked at this project three months ago and thought, "not ready yet" and now I feel it is certainly ready. Sure it will always need work and the more automation the better but this is top shelf guys... well done.
/W
I'm having a bit of trouble trying to figure out how to pass more complex objects into the extension. for example something like this to allow vertex arrays via the "OES_vertex_array_object" extension, which should have the same signature as webgl2's native create_vertex_array() / bind_vertex_array()
it seems create_vertex_array_oes() is working fine, but when I try to pass that into bind_vertex_array_oes() I get errors.
Also tried different approaches (not using option, not using refs, etc.)
Any help is appreciated, thanks!
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = OesVertexArray)]
pub type OesVertexArray;
#[wasm_bindgen(method, getter, js_name = createVertexArrayOES)]
pub fn create_vertex_array_oes(this: &OesVertexArray) -> Option<WebGlVertexArrayObject>;
#[wasm_bindgen(method, js_name = bindVertexArrayOES)]
pub fn bind_vertex_array_oes(this: &OesVertexArray, target:Option<&WebGlVertexArrayObject>);
}
@dakom can you open a new issue with details as well to the error you're seeing? Some code to reproduce would also be great!
Nevermind - I see this extension is actually bundled as part of web-sys now :)
https://docs.rs/web-sys/0.3.23/web_sys/struct.OesVertexArrayObject.html
Most helpful comment
@dakom You can use
Reflect::getto access the members and thenReflect::applyto call them.But that's pretty terrible (and slow), so a much better approach is to create some bindings for it:
Then you can convert your
Objectinto anAngleInstancedArraysby using this:@alexcrichton @fitzgen Can we somehow auto-generate bindings for the WebGL extensions? There is IDL for it.