-
Notifications
You must be signed in to change notification settings - Fork 51
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
Web support via stdweb and web-sys #26
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I've added comments where I think changes should be considered, but I'm excited to get support for this.
src/lib.rs
Outdated
@@ -46,7 +46,10 @@ pub mod windows; | |||
#[cfg_attr(feature = "nightly-docs", doc(cfg(target_os = "ios")))] | |||
#[cfg_attr(not(feature = "nightly-docs"), cfg(target_os = "ios"))] | |||
pub mod ios; | |||
// pub mod wasm; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be a line break here for consistency reasons.
src/web.rs
Outdated
#[cfg(feature = "web-sys")] | ||
pub canvas: web_sys::HtmlCanvasElement, | ||
#[cfg(feature = "stdweb")] | ||
pub canvas: stdweb::web::html_element::CanvasElement, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like this design for conditionally selecting the canvas
type. APIs that behave differently should look different, and overloading the canvas
name will make this type significantly harder to use, understand, and document.
Ideally we can follow the same approach we use for selecting the X11
/Wayland
backend: have different variants in the top-level enum for each backend (assuming we don't switch the HTMLCanvasElement
representation we're exposing). That being said, I assume there's a reason you made this design choice over the one I just outlined - is there any technical reason why that's a bad idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My reasoning was 'Winit and X11 are both valid choices in the same binary, but stdweb and web-sys are not.' With that in mind, if they should still be separate I have no problem separating them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sympathize but since they're not actually the same API, as a user I would prefer that they be entirely different things in the struct.
Cargo.toml
Outdated
[target.'cfg(target_arch = "wasm32")'.dependencies.stdweb] | ||
version = "0.4.18" | ||
optional = true | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely comfortable with re-exporting these types in our public API, since it opens us up for breaking changes if the downupstream crates ever bump their major version.
Looking at the stdweb
source code, it looks like the Canvas
struct just wraps around an i32
that specifies the HTMLCanvasElement
JS object. Could we expose that i32
instead of the higher-level wrappers, than have downstream users reconstruct the object from that integer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to look into ways to remove the stdweb and web-sys types from the public API, which should also possibly help with my problem that they aren't 'Copy'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would using Box::into_raw and Box::from_raw on the canvas objects make sense as a design? Then the handle can just be a void*
.
The downside is a serious loss of safety, but the upside is that it's more in line with the rest of the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryanisaacg I'm not entirely comfortable with doing that, since it seems like an unnecessary layer of indirection over exposing the JS reference integer directly.
stdweb
's Reference
type exposes unsafe from_raw_unchecked
methods for internal use. Could we see about exposing those methods in the public API? From a light investigation it seems the main reason they aren't exposed is because the authors didn't think there was much reason to expose them (based on koute/stdweb#339), but I think we've got an acceptable reason here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll propose upstream methods to stdweb and wasm-bindgen to have unsafe methods for converting back and forth between the integer ID's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting ourselves up for either a breaking change or forcing our users to use legacy code would fundamentally undermine the stability and common ground that this library is supposed to provide, and as such is an unacceptable solution.
In the thread you linked, there's a point in @alexcrichton's comment here (rustwasm/wasm-bindgen#999 (comment)) which strikes me as strange (emphasis mine):
I think you're right that taking advantage of future wasm feature "in their fullest" is likely a breaking change, but what I was hoping for is that it's a largely cosmetic breaking change rather than "rewrite the world" breaking change. For example switching some types around is pretty easy, but losing a fundamental capability (like "O(1) conversion to an integer from JsValue") runs the risk of making it much harder to migrate in the future.
Wouldn't changing an unsafe JsValue::from_raw(i32)
method into JsValue::from_raw(anyref)
just be a cosmetic breaking change? You aren't losing the ability to convert arbitrary integers into JsValue
, because such an API would never provide that guarantee to begin with. Unsafe code can require additional semantics for proper use, and as long as a from_raw(i32)
method requires handling the raw i32
similarly to how you'd handle an anyref
variable you shouldn't run into any major compatibility issues when you switch the types over.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, let's think about this. The whole point of this is to expose window handle stuff as primitive types that are NOT bound to a particular version of a library. And the problem is that JsValue
's are not primitive types, quite, or rather wasm-bindgen
doesn't want to be able to treat them as such because the fact that they're an i32 under the hood is an implementation detail that quite realistically may change. So, if we DID expose wasm-bindgen
's JsValue
as integers... it would be subject to breaking changes anyway.
So, we can't expose the raw types under JsValue
because it wouldn't be stable, any more than we can expose the layout of whatever structure a HWND
actually points at. One solution is that raw-window-handle
could expose handles based on the version of wasm-bindgen
, such as WasmHandle02(JsValue)
, WasmHandle03(JsValue)
, and so on, and use feature flags to offer the right ones at compile time. It would work. But it would rather suck.
I brought this up for discussion again here: rustwasm/wasm-bindgen#1766
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on the Rust Community discord, if we're willing to limit ourselves to canvases that exist within the DOM, we can provide some sort of UUID that windowing libraries attach to canvas elements. Then, clients can find the canvas via the UUID.
Upsides:
- We're not tied to stdweb or web-sys under the hood
Downsides:
- Requires a bit more work on behalf of the windowing libraries (probably not too bad)
- Does not account for canvases not inserted into the DOM (probably not important, because this library is for interop from windowing libraries)
Would this work for everyone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be okay with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's kinda a hack IMO, but it's a hack that should work and make it possible to use right now without needing to wait for someone else to figure their stuff out. Which is partially the point of this library.
Ok, I've pushed up a change with a new design that doesn't tie us into the API of web-sys or stdweb. |
src/web.rs
Outdated
pub struct WebHandle { | ||
/// An ID value inserted into the data attributes of the canvas element | ||
/// | ||
/// Each canvas created by the windowing system shoudl be assigned their own unique ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*should
src/web.rs
Outdated
/// ``` | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct WebHandle { | ||
/// An ID value inserted into the data attributes of the canvas element |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't specify the name of the canvas attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Looks good to me after the fact 👍
Old PR:
This will probably not be the final change, because it:
Some aspect of web support does need to make it into raw-window-handle for web support in winit, but I wanted to put up this PR to start discussion on what that should look like.
Edit: For more context, the Canvas objects in stdweb and web-sys are Clone but not copy, so a struct containing them may not be Copy either. I'm not sure of the best-practice way to work around this.
New PR:
A backend-agnostic numerical ID for web has been added as an option to the window handle enum, with documentation referring users to custom data attributes on HTML elements.