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

Add ability to import and extend JS classes #210

Open
willmruzek opened this issue May 24, 2018 · 10 comments
Open

Add ability to import and extend JS classes #210

willmruzek opened this issue May 24, 2018 · 10 comments

Comments

@willmruzek
Copy link

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?

@alexcrichton
Copy link
Contributor

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

@willmruzek
Copy link
Author

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
Copy link
Author

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.

@jsheard
Copy link
Contributor

jsheard commented May 28, 2018

cargo-expand should do the trick.

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

@willmruzek
Copy link
Author

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

@willmruzek
Copy link
Author

willmruzek commented May 28, 2018

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()");
  }
}

@jhpratt
Copy link

jhpratt commented Mar 20, 2019

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

@fitzgen
Copy link
Member

fitzgen commented Mar 21, 2019

@jhpratt no updates; you may be interested in reading the discussion in rustwasm/team#162 however.

@SephReed
Copy link

A couple links to what led me here.


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.

@maxwalley
Copy link
Contributor

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

enmand added a commit to enmand/dwn-rs that referenced this issue Apr 8, 2024
- Since wasm-bindgen doesn't support a way to extend JavaScript
classes (rustwasm/wasm-bindgen#210), add a basic JavaScript shim, that
pushes the data available in Rust to the Readable in JavaScript.

- use channels and spawn_local in Rust to move along Stream iterator
and pass results to enqueue for read() (in the JavaScript shim)

- adds an abort controller that will abort the stream in JavaScript
is a stream error occurs in Rust
enmand added a commit to enmand/dwn-rs that referenced this issue Apr 8, 2024
- Since wasm-bindgen doesn't support a way to extend JavaScript
classes (rustwasm/wasm-bindgen#210), add a basic JavaScript shim, that
pushes the data available in Rust to the Readable in JavaScript.

- use channels and spawn_local in Rust to move along Stream iterator
and pass results to enqueue for read() (in the JavaScript shim)

- adds an abort controller that will abort the stream in JavaScript
is a stream error occurs in Rust
enmand added a commit to enmand/dwn-rs that referenced this issue Apr 8, 2024
- Since wasm-bindgen doesn't support a way to extend JavaScript
classes (rustwasm/wasm-bindgen#210), add a basic JavaScript shim, that
pushes the data available in Rust to the Readable in JavaScript.

- use channels and spawn_local in Rust to move along Stream iterator
and pass results to enqueue for read() (in the JavaScript shim)

- adds an abort controller that will abort the stream in JavaScript
is a stream error occurs in Rust
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants