wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

Add ability to import and extend JS classes

Open willmruzek opened this issue 7 years ago • 11 comments

JS classes are heavily used building block in UI development.

It's common for a library like ReactJS or Polymer to provide a component class to extend from.

Thus, there should be an easy way to interoperate with classes, extend them in Rust, and export them back to JS.

I don't know about Rust to know what's possible yet. But I imagine we could use attributes to annotate when a Rust struct inherits from a JS class?

willmruzek avatar May 24 '18 01:05 willmruzek

Agreed this'd be great to have! I'm not 100% sure what this would look like, but would love to see and help explore options here

alexcrichton avatar May 24 '18 03:05 alexcrichton

Cool! I'll do some research into how this can be done.

I've already looked at bindgen for C++ and didn't find an immediate solution.

willmruzek avatar May 24 '18 13:05 willmruzek

Is there a way to expand (procedural) macros to see the text output of wasm_bindgen? It would be helpful as I learn more about how this all works.

willmruzek avatar May 28 '18 13:05 willmruzek

cargo-expand should do the trick.

rustup component add rustfmt-preview
cargo install cargo-expand
cargo expand --target=wasm32-unknown-unknown > expanded.rs

jsheard avatar May 28 '18 13:05 jsheard

Thanks @jsheard. I think I have it working now.

willmruzek avatar May 28 '18 13:05 willmruzek

This is the first time diving into something like this, so this may be a naive suggestion.

It looks like a class is imported as a struct with a bunch of method impls. Would it be possible to construct a trait via the macro as well? Though looking into it, we can't yet bind trait implementations to JS.

Note I've added #[wasm_bindgen(extendable_as = "FooT")] to allow for backwards compatibility.

JS:

export class Foo {
  print() {
    console.log('Foo.print()');
  }
}

Generated Rust:

trait FooT {
    fn new() -> Self;
    fn print(&self) {
     // wasm-bindgen magic 
    }
}

struct Foo;

impl FooT for Foo {
    fn new() -> Component {
        Component
    }
}

Rust usage:

#[wasm_bindgen]
extern {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[wasm_bindgen(module = "...")]
extern {
    #[wasm_bindgen(extendable_as = "FooT")]
    type Foo;

    #[wasm_bindgen(constructor)]
    fn new() -> Foo;

    #[wasm_bindgen(method)]
    fn print(this: &Foo);
}

#[wasm_bindgen]
pub struct Bar {}

#[wasm_bindgen]
impl FooT for Bar {
  fn print() {
    log("Bar.print()");
  }
}

willmruzek avatar May 28 '18 14:05 willmruzek

Any updates on this? I was looking to see how feasible it would be to create webcomponents using wasm as an experiment, but it's necessary to extend classes for that (either HTMLElement or a framework-specific class).

jhpratt avatar Mar 20 '19 05:03 jhpratt

@jhpratt no updates; you may be interested in reading the discussion in https://github.com/rustwasm/team/issues/162 however.

fitzgen avatar Mar 21 '19 22:03 fitzgen

A couple links to what led me here.

  • Stack Overflow Question - https://stackoverflow.com/questions/63893000/extend-a-web-sys-struct-in-wasm-bindgen-specifically-audioworkletprocessor-in
  • Feature Request - https://github.com/rustwasm/wasm-bindgen/issues/2308

It would be really amazing to be able to extend the AudioWorkletProcessor! IMO, audio work is one of those things which is very well suited to the web, but has never been possible due to the limitations of JS (single thread, slow).

Each AudioWorkletProcessor is its own thread, and having one of those exist in the wasm sphere would ~10x the audio-synthesis ceiling (+/-).

The issue is that one must extend AudioWorkletProcessor and re-export it in order to use it in wasm.... so web audio will have to wait once more.

SephReed avatar Sep 15 '20 16:09 SephReed

For anyone still looking for the Audio Worklet functionality there is some documentation on how to do it here: https://rustwasm.github.io/wasm-bindgen/examples/wasm-audio-worklet.html

maxwalley avatar May 01 '23 13:05 maxwalley

@alexcrichton, would work on this require an RFC?

punkstarman avatar Apr 08 '25 15:04 punkstarman