koute / stdweb

A standard library for the client-side Web
Apache License 2.0
3.45k stars 177 forks source link

Custom Elements / Shadow Dom #32

Open Boscop opened 6 years ago

Boscop commented 6 years ago

How to use shadow DOM with this library (to apply styles only locally in custom elements)?

koute commented 6 years ago

You mean, this?

There are currently no bindings for it here, although you're welcome to add them if so you wish. (It doesn't look like it has a big API surface from the MDN page.) You can also always use the js! macro and use the JS API directly.

NeverGivinUp commented 6 years ago

@koute I'd like to second @Boscop on custom elements.

Web components are well encapsulated, communicating over attributes as a defined interface and have their own lifecycle, with callbacks for connection/disconnection to the dom as well as attribute changes. This interface does not expose the implementing language. According to MDN Chrome and Opera have enabled most features by default . Firefox has experimental support and will enabled them by default by about version 61. Safari supports less than the above browsers, and Edge is working on an implementation. By the time most browsers have stable implementations, Rust-wasm might be ready, too. Writing custom elements is a great early use case for rust in the browser. Especially for computationally costly components drawing on the canvas.

What I don't know is if they each would need a distinct memory space that cannot be shared with other components and might bloat the consumption.

I would try to add them, but my understanding of idiomatic rust is very(!) limited. I'd need a lot of mentoring starting with: what is the rust way of telling someone that it wants to observe attributes and then be informed about their change. The JavaScript functions are approximately attributeChangedCallback(name, oldValue, newValue) => void and observedAttributes() => Array, where 'name' and the values in the returned strings are names of attributes. Rust (I believe) has no reflection. Most likely you already implemented a solution for this. But I don't know where to look for it right now. Also, this conversion of attributes might be a subject for the tutorial @mgattozzi suggested for the Rust wasm Book.

Pauan commented 6 years ago

@NeverGivinUp I might be completely wrong, but my understanding is that each WebAssembly module has its own linear memory, so some amount of bloat is probably unavoidable.

However, there are two things to keep in mind:

1) It's possible to import the linear memory of another module. When dynamic loading is supported it should be possible to link to a common library (and thus reuse memory).

2) Rust has a very minimal runtime (and doesn't use a garbage collector), so the bloat should be pretty small (however, Rust is not optimized for code size, so keep that in mind as well!)

As for implementing APIs in stdweb, either @koute or myself would be happy to help explain how stdweb works.

The custom element API seems particularly tricky to implement. I'm not sure if it requires ES6 classes, or if ES5 class-likes can be used. Either way, it'll require quite a lot of work to support it.

The way I would go about doing this is creating a new CustomElementBuilder struct. That struct would have a bunch of methods allowing you to specify various attributes, methods, etc.

Then you'd call the done method which will create an ES6 class and return a CustomElement struct. Lastly you would pass that CustomElement struct to custom_elements().define("foo", foo, Some("p"));

This is a super high-level overview, there's a ton of details to work out, but that's how I'd start.

Alternatively, maybe it would be easier / better to use a macro, though macros in Rust are currently not very good.

mgattozzi commented 6 years ago

@NeverGivinUp I could see this being one of them possibly :) To keep this thread not polluted with that discussion can continue in rust-lang-nursery/rust-wasm#41