-
Notifications
You must be signed in to change notification settings - Fork 67
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
Browser support #42
Comments
A browser build would be straightforward to add, and we could support all API methods except for |
+1 as I'm running into this now when I try to import // in the browser, doesn't work
import { transpile } from '@bytecodealliance/jco'; It can't be done because top level await and a module called "module" that Webpack inserts. Even if I were to import it, could I call |
Dug a bit deeper, I noticed that let { files, imports, exports } = generate(component, opts); ...we could use rollup to bundle those deps into a script directly usable by the browser. |
That only works if you work on the assumption that the artifact can/should be changed for different targets. If you want to be able to deploy a single wasm component and have it run in multiple environments, having to then do a separate step for just the browser defeats a decent chunk of the purpose. Especially for use-provided logic. |
I'm confident we can streamline it all in JavaScript, and all in the browser pretty efficiently, we just need to chip away at it piece by piece. I've already written the |
@guybedford I finished writing the Rollup Plugin 🚀 https://github.com/DougAnderson444/rollup-plugin-wit-component This plugin essentially bundles all the dependencies from // import { generate } from 'obj/js-component-bindgen-component.js'
let { files, imports, exports } = generate(wasmBytes, opts); into a single file that browsers can use to This bundling step can even occur in the browser itself! That is what the demo does. The plugin can be used on it's own, but in my mind it would make more sense to somehow make it available from |
@DougAnderson444 this is awesome!! For the browser support, that definitely should be upstreamed I think, would you be interested in upstreaming this? Or is it only working because you managed to work around the FS by avoiding WIT deps and stubbing out the WASI dependencies in the build? The online demo looks great - would be amazing to have an interactive demo. |
When I try to use I was able to re-use most of the code from jco, including the WIT deps I think you are referring to. Glad you agree it should be upstreamed for browsers, I am happy to help where I can. I do think jco should be exporting ES modules in the dist as well, perhaps we can incorporate that at the same time. I'm surprised you didn't use rollup for jco? I was thinking of an interactive demo too, I really like the browser stuff over at wasmbuilder.app and I've been thinking of ways to either incorporate it there or do something similar. The demo would have to pull out the function names and input types and make a best-guess form to call the functions. I'll figure something out. |
Good to know - we can update the JCO internal build to use the If we got that resolved what would be remaining to support it being a direct import of the plugin?
I'm open to changing the build to move away from ncc, not tied to it by any means. For interactive demos, we used to have a really nice live WIT bindgen demo here - https://bytecodealliance.github.io/wit-bindgen/. It is no longer maintained though but may help for inspiration. |
We're getting there, but there still seems to be a bit of a nodejs dependency that I can't seem to get Vite to work around:
Looks like it's coming from here: Lines 134 to 138 in dd8822c
|
ora is a terminal-specific library - so I'd suggest abstracting the spinner out to an interface/proxy object, and then using ora only in the command line/node version of the library. You can potentially use https://www.npmjs.com/package/@rollup/plugin-alias or https://github.com/KeJunMao/vite-plugin-conditional-compile to provide a different version of the spinner in node and on browser, or just have a stub browser implementation that does nothing... |
A browser shim would be great, I've started some work on that in #97. If someone wants to pick this up further that would be a huge help! |
Hello, I am interested in running Current solution Ideal solution Making it synchronous? A pure Rust solution |
Compiling WebAssembly modules is always asynchronously. |
Maybe from JS, but not from Rust. The WebAssemnly::Module::new function is You can then put this method into a JS closure and pass it to JS, and now you have a JS function that compiles bytes to wasm synchronously. I am already using this approach in wasm-bridge; for example, here I "massage" the "instantiate" function so that it is synchronous and a "normal js function" instead of an module with exports, and here I pass the synchronous "load wasm" function to JS. |
Looks like the |
Good digging. I guess exporting both options (sync for convenience and async for non-blocking performance) and letting the user decide which they want to use would be best. |
Keep in mind that What I would do for your project is use |
Yes, that's what I am doing. In fact, here is the But this requires the user to manually convert the components using jco. If jco would run on the web, they could use the original wasm component and my crate would transpile it during runtime. This would be slower at runtime, but more convenient. Although, I have noticed your example is using wasi, so I will definitely look into that. EDIT: Oh wait, you use the JS runtime. That definitely helps too, but I want to see an example of wasmtime rust runtime running a wit component with wasi (not really related to this issue that much, but doesn't hurt to ask). |
That is exactly what my rollup plugin does :) There is a bit of work to be done to incorporate it directly into
I think you can also use
You can check my other repo https://github.com/DougAnderson444/wit-wasm I think is what you are looking for? |
Yes, I understand, I I think the names are a bit confusing too. There is an adapter that converts from Then it is linked using preview2 in As far as putting it together, yes also a confusing complicated step. We really ought to write a Blog post, but this stuff was changing so often I wasn't sure if the Blog would be obsolete very soon. |
Hello @DougAnderson444 , the jco rollup plugin is working well. I was able to remove the dependency on If I understand correctly, the bindgen "module" is jco componentized to a wasm component and then transpiled by (essentially) itself to run on the web? That is getting pretty meta, but it works. Future collaborationWhat I wanted to ask is if I can add this folder that contains your "generate" plugin to wasm-bridge? This would allow the end user to use the same component bytes on desktop and on the web, which would be awesome. Different imports?Also, I noticed that the import functions are specified differently to when using jco "normally". I need to add another "layer" into the import object like this: // from your plugin
"import-point": {
default: {
importPoint(point) {
point.x = point.x + 100;
return point;
},
},
}, instead of this: // from using jco in command line
"import-point": {
default(point) {
point.x = point.x + 100;
return point;
},
}, This isn't anything that cannot be worked around, but it is slightly annoying. What version of jco did you use? I am using 0.9.4. This is my wit file: package example:protocol
world my-world {
record point {
x: s32,
y: s32,
}
import import-point: func(pnt: point) -> point
export move-point: func(pnt: point) -> point
import print: func(msg: string)
// Say "Hello" to stdout, use with wasi
export say-hello: func()
} TS bindings also wrongThe TS bindings generated by the plugin are even worse. Not only do they not match what the code is doing, they flat out can never work, because they define two "default" functions with different signatures: // from your plugin
export interface ImportObject {
default(pnt: Point): Point,
default(msg: string): void,
// wasi stuff...
} Jco version 0.9.4 generates the types correctly (with --instantiation, which I am using too): export interface ImportObject {
'import-point': {
default(pnt: Point): Point,
},
print: {
default(msg: string): void,
},
// wasi stuff ...
} |
Ok, Google Chrome on mobile doesn't seem to like it:
and neither does Samsung Internet, but I couldn't get the error trace. Looks like I will have to not be laze and do the asynchronous compilation after all. Anyway, that is kind of off topic. |
That's awesome that you were able to streamline the code! Amazing that this works in the browser =D
I am a big fan of having everything compile in the browser if possible. Have you checked out https://wasmbuilder.app/?
Yes that would be amazing too!
I looked back at the code, it was using Version But your method without Rollup seems to be more streamlined? |
That looks really cool. When I hover over the exports/imports, it doesn't tell me what it is (for example, signature for functions, etc), but otherwise, it is pretty interesting. Also, I am no longer using that solution. I have code in Rust that is compiled into wasm32 and needs to load and execute wit components, and it turns out I can just use js-component-bindgen directly, instead of transpiling it by jco. But you are welcome to use the tricks (or hacks, to be precise), from the repo I linked before to streamline the use of your rollup plugin. |
@kajacx are you trying to run that |
@DougAnderson444 You can't load it directly, but you can load the transpiled component with Your Rust code will load a wasm component, and then wasm-bridge will transpile it using the Rust crate that jco uses, and then gives the result wasm module to the browser via js-sys. For the end user, it works exactly the same way as on desktop, they can have one singe source core in Rust that loads and executes wasm components the same way you would do it in wasmtime, but it works on desktop as well as on the web. |
Hey @guybedford, everybody, as a hackathon project last week we did PoC of browser host in just JavaScript Good part: it has just 35KB! If anyone is interested to help, please reach out directly to me or open an issue on jsco project. |
I did like to use jco for handling wasi preview2 in browser_wasi_shim. Is it possible to use jco directly in the browser to take a wasm component, run the transpilation step and directly run it as a shim until browsers natively support the wasm component model? Or does it only run in nodejs and does it only support writing out javascript files to the filesystem that can later be imported rather than directly evaluated using
new Function
oreval
?The text was updated successfully, but these errors were encountered: