-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Implement shim_url
#3247
Implement shim_url
#3247
Conversation
Similarly to #3168 should I return a |
be1385b
to
e1f7641
Compare
Rebased after #3272 and #3279. @Liamolucko friendly ping. |
Rebased after #3329. |
I think the better way to implement this are shim format-specific getters. For example,
More format-specific getters could be added for other formats (like |
Isn't this solved by using
See #3355, but generally I'm in favor of deprecating when we reach that point. |
Co-authored-by: Liam Murphy <liampm32@gmail.com>
The problem is that existing crates (without updates) will compile with |
That's a really good point actually. I would like to suggest to merge (CI got stuck btw) |
That sounds great, assuming I understood you properly! To be clear, do you mean something like: fn shim_url(format: ShimFormat) -> String { ... } Which then returns the URL of a shim with the format you passed in? Just double-checking because what you're describing also sounds kinda like: fn shim() -> (String, ShimFormat) { ... } Which I wouldn't be particularly in favour of. |
I was actually suggesting: fn shim() -> Shim { ... }
enum Shim {
EsModule { url: String },
NoModules { url: Option<String>, global_name: String },
...
}
// or maybe:
struct Shim {
url: Option<String>,
format: ShimFormat,
} But your suggestion with passing in the format might be better if we want to support getting multiple shims? Or we could return a Personally, if we go the route of wanting to support multiple shims I would prefer returning a |
Ah, I see, you were talking about @lukaslihotzki's comment that crates would break when they didn't understand the shim format. I thought you were talking about their suggestion to support multiple shims. I don't think that combining Supporting multiple shims solves that, since the crate can pick whatever shim it likes, and doesn't have to worry about what shim the current target is using, if it even has one. I do think that moving to an enum like that is an improvement if we stick to the one-shim approach, but I'm now leaning more towards having multiple shims here as well as in linked modules. @lukaslihotzki makes a good point that it makes it a lot easier for crates to be target-agnostic, and makes it possible for this feature to work on As for how that would actually work, the version of So, there wouldn't be a problem of needing multiple calls to 'find' a shim like you were describing. |
Thanks, I see what I misunderstood here. I'm starting to question the multiple shims approach. The advantage of having multiple shims is that a library maintainer doesn't have to think about what shim the user currently uses, but gets whatever they desire. This actually comes with an overhead though, multiple shims have to be bundled into the application. But of course supporting each shim separately comes with a higher maintenance burden for a library maintainer. Not that I'm against the idea of multiple shims, but I think it's a choice users should be able to make. For example I don't use a bundler and I don't have any snippets either. I have a single JS file that I can minimize and serve and that's it, I don't want to buy into the overhead the bundler target brings with it. Also I'm not sure how this is supposed to work with the no-modules target, when I use the no-modules target I do it for compatibility purposes, an underlying library can't just use the web target, that would break my build, I want it to use what I use, if it doesn't support it then I have to fix the library or get another. Even if we deprecate the no-modules target, not all future targets will be compatible with each other. So the conclusion I'm coming to while I'm writing this is that it's an interesting idea that we could support importing any desired shim, but my use-case still requires the current approach of requesting the currently used shim and act appropriately. I would also like to understand exactly how the bundler target works, I mentioned before that I have no clue of the JS ecosystem, I don't know what Webpack is and I've never used a bundler before. Taking a brief look at this stuff, it seems quite straightforward to me, they bundle all the files together, probably doing minimization at the same point too. My understanding is that the bundler target doesn't work without actually using a bundler on the generated files, so how exactly would that work if a user uses the web target but a library pulls in the bundler target shim? Apologies for the naivety on this topic. |
The overhead should be small, because shims are usually much smaller than the Wasm module. For wasm-audio-worklet (very small app), the shim size is 17% of the Wasm size (both compressed). In a more interesting project that uses winit and wgpu, the shim is only 1.5% of the Wasm. Also, the size of extra shims can be optimized by sharing code between them. ES module shims (like bundler and web) can
There is no overhead if you request the shim url of the native format of your target. If your manual build setup does not support linked modules, omit
If a library creates an audio worklet and uses the ES module shim in there, that should work fine even if
You can still change the library or choose another to match your native format. The difference with multiple shims is that users aren't forced to do it, if they accept the usually very low overhead. Also they can still do it at later time when their product works, but the shim size needs to be optimized. |
I don't disagree that the overhead is small, I would still prefer not to pay for it.
That would be really nice but I'm concerned with this idea of "future optimization", In any case, I agree that whatever overhead I was talking about is negligible and I'm happy to accept it for a better feature.
I agree, but that requires an API that actually can request the native format, the API we were discussing above might suggest that we can't: fn shim_url(format: ShimFormat) -> String { ... }
Audio worklets support both, but web workers don't, on Firefox they don't support ES modules (the web target). But that is not the whole story, yes, Firefox will support it eventually, and then we can drop this point too. But what about future targets? Let's say the component model is introduced, we will need a new target for that, maybe that will only be supported on some browsers, or maybe only in the window but not in workers, or any other scenario. This idea of making multiple shims available on demand only works if all targets are actually compatible with each other, which they are definitely not right now and we can't predict that new targets will be in the future.
I agree. I want to emphasize I'm not against the idea of having multiple shims, but it doesn't work for all use-cases and I want to make sure we support at least the native approach! |
No, audio worklets do not support
If you are the application developer, then you should know your target and choose the appropriate format. If you develop an independent library, you have to choose a format suitable for most of your users and suggest to use a corresponding target to your library users. The library users that choose a different format regardless will prefer a larger product compared to a broken product. If a library developer wants to provide different native formats, we could add a macro like |
Okay I'm starting to see the issue here. I was under the assumption that the proposal is to expose multiple shims to make it irrelevant for library developers which shim they pick compared to which shim the user picked. Now the feature actually makes sense to me 😅!
You can still use audio worklets on Firefox with the no-modules target by not using But absolutely, multiple shims would solve that problem much better, now that I understand the proposal it makes perfect sense.
I agree that this is how it will likely play out anyway. So, after (hopefully) finally understanding the full picture here, I'm also strongly in favor of supporting multiple shims. About #3168 and #3247, I have some concerns and arguments why we should still merge them, more or less as-is. I'm gonna start with that if we still want to support querying native modules in a macro, like I am also concerned about the timeline here, this will take a long time to develop and to get right. Comparatively The main argument against it, which would be that we encourage libraries to depend on these features which could be harmful in the long run, is something that I now understand. This wouldn't be a problem if we could remove them again in a version bump, but I can only assume that this isn't going to happen anytime soon. But I also don't think it's a huge deal and I'm not sure how harmful this can really be. Wasm and browsers are a moving target and libraries have to update and adjust anyway. I do still think though that combining |
What's needed to move this forward? I'm wanting to use an AudioWorkletProcessor but it's not as easy as I was expecting. This seems like it will remove some of the boilerplate that I need. |
#[wasm_bindgen]
extern "C" {
type Meta;
#[wasm_bindgen(js_namespace = import, js_name = meta)]
static META: Meta;
#[wasm_bindgen(method, getter)]
fn url(this: &Meta) -> String;
}
let shim_url: String = META.url(); Is what you can use now, though it won't work with the no-modules target. I will close this PR as its no longer planned. Not only do we plan to #3355 but now all browsers support ES modules in audio worklets. |
Adjusted #3032 according to @Liamolucko's comment: #3032 (comment).
This is now only implemented for the
web
andno-modules
targets, all other's returnNone
.Replaces #3032.