Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to call function on an object? #1428

Closed
dakom opened this issue Apr 7, 2019 · 8 comments
Closed

How to call function on an object? #1428

dakom opened this issue Apr 7, 2019 · 8 comments
Labels

Comments

@dakom
Copy link
Contributor

dakom commented Apr 7, 2019

Summary

Given a js_sys::Object, how do you call one of its functions?

Additional Details

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 dakom added the question label Apr 7, 2019
@Pauan
Copy link
Contributor

Pauan commented Apr 8, 2019

@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.

@alexcrichton
Copy link
Contributor

I think this is a duplicate of #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 #893 which I think #1405 may help start paving the path towards implementing.

@dakom

This comment was marked as abuse.

@Pauan
Copy link
Contributor

Pauan commented Apr 14, 2019

@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.

@WolfieWerewolf
Copy link

@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());

image
@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

@dakom

This comment was marked as abuse.

@alexcrichton
Copy link
Contributor

@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!

@dakom

This comment was marked as abuse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants