I was surprised to find out that there's a code_review category here. I don't work with Rust professionally (hence I don't have Rust colleagues to push me) so it would be amazing to get some feedback on how I'm doing!
I'm mainly interested in feedback for Rust specific patterns, but any general observations will also be appreciated!
It's worth noting that ECS is probably the best approach for a generic game engine, but I wanted to keep the scope small and simple.
I implemented a procedural macro as well - obviously a flexible component system would have avoided the hardcoded renderables and transform properties, but the macro code is what's important for the review!
I have not looked into your code but I notice you mention the overheads of communicating between WASM and Javascript. The YouTuber Tsoding seemed to have a great solution for that. As I remember it basically involved setting up an area of memory that is accessible both from WASM and Javascript, as some kind of byte array I guess. Then the WASM renders into that buffer which is immediacy visible to the Javascript and can be blitted into a canvas as an image. This way he managed to get frame rates of 60fps and more. Also he could migrate his rendering, part by part, from his original JS code to WASM. Both rendering into the same buffer. See here: https://www.youtube.com/watch?v=MpfKdyMGPRA He has a short series of vids on this so you might need to check them all.
I've done something similar. Although I'm not directly writing the image data in WASM (instead numerical data to plot) the concept is the same.
The JavaScript code to construct an array backed by the same memory as WASM is here. It uses the wasm_bindgen::memory() function and a (mut) pointer to the WASM data. I got this in JS land by exposing a function in the #[wasm_bindgen] block which returned the result of a call to Vec::as_mut_ptr; for example.