 So the goal for this talk was I wanted to give as clear a picture as I can of what the JavaScript integration for components looks like. And unfortunately, the best way to do that is really just to demonstrate it, which means this is a demo heavy talk. And so hopefully it goes well, but please bear with me if it doesn't. And it's also very difficult to estimate timing with demos, so we might have to skip some things. I don't really see how it goes, and hopefully things run smoothly, but just fair warning in advance. My hope is that you will walk away with a good sense of how to use these tools, how to apply these tools, and sort of where they fit into the overall component model workflows. So to just do a little bit of motivation first, I'm going to take a step back and look at the overall JavaScript ecosystem itself. So when we talk about the JavaScript tool chain for assembly components, we're integrating with this JavaScript ecosystem, which is a modular JavaScript ecosystem where we're running a whole bunch of JavaScript modules, and we're packaging them up and running them in browsers. Firstly, we're packaging up a whole bunch of code from NPM on node modules. This is running as common JS, and more recently, native modules. We've found a third of the way through the transition into proper native modules in JavaScript, and that's sort of an ongoing process, but we're sort of getting to a place where you've got sort of native modules, and you can run them with these kind of module semantics in the browser, in Node.js. We have other JS environments like Dino, and more recently, we have these kind of edge environments that all want to run JavaScript and run JavaScript modules, and the new kit on the block is Bun, which I think is going 1.0 tomorrow, so that's probably one to look out for. And when you're running JavaScript in all of these environments, you also want to be able to run WebAssembly along with your JavaScript, and so the sort of ideal that WebAssembly can be something that can just embed in JavaScript like any other JavaScript module is a nice ideal to think about, but in reality, you have a whole bunch of JavaScript blue code, and you have a WebAssembly module, and then you have a whole bunch of sub-processes running WebAssembly modules, and a whole lot of blue code doing marshaling with all this, and this is great. It allows for the creation of incredible applications, but if you are a library author, if you want to write code that's going to be shareable and embeddable and different, if you think of all these different run times that we're running JavaScript in, you're going to need a glue, and what do I mean by the glue? Well, this is a good example, so like ESBuild is a library that's a modern build tool for JavaScript, a really nice one written by even Wallace, and if ESBuild needs to be run from Wasm, it needs to be instantiated, so you need to find the Wasm, so you need to fetch it from a URL, you need to compile it, you need to instantiate it with the go runtime, and then you can finally get your transform method, and this is just like a tiny bit of glue, obviously normally in Wasm modules you have a whole bunch of JS glue to achieve these sort of things, but this is sort of like absolute minimum if you want to run ESBuild, and then if you want to run a library like ESBuild in all of these other run times, how are you going to even be able to achieve that? For example, you're using the URL spec, the fetch spec, assuming that you can load a file URL, if this is a file scheme that you're running your modules on, will your bundler even include that Wasm? For example, Node only just very recently got support for fetch, but it doesn't support file URL, so this technique doesn't work in Node, and so you now have to have branches, and if you mention that we've got all these different run times that we're running on, you're going to have a whole bunch of branches. As a library author, it becomes more and more of a nightmare to maintain libraries that can run in different environments and be embeddable first class, and so if we want to reduce this glue, well, we've got the ECMAScript module integration for WebAssembly, and this integrates WebAssembly with the ESModule system, and more recently we have the source phase import proposal, which allows importing uninstantiated WebAssembly modules in the ESModule integration, and using this approach, we can kind of replace this glue with just a direct source import of ESModule, so you import ESModule as a module, it's through the module system, you'll build to understand it, it's statically analyzable, and now we just have to instantiate the run time, but we still have that run time instantiation step. So what's stopping us from getting straight to importing from Wasm? Well, first class embeddability, and this is where the component model comes in, so the component model solves for the embeddability problem of Wasm, it gives you these rich interfaces, it's got all the types, and it has first class instantiations, which was the main piece of our glue. It leans into imports as capabilities, which JavaScript can't do because it has a spillage over its interfaces, whereas the component model has a shared nothing linkage boundary, which has a lot of strong security properties that we're able to lean into. And so using the component model, if we were to look at this JavaScript module, I could imagine embedding an equivalent component that would look something like this, and please look away, I haven't got it 100% right. So you could have something like this, where you could import this build as a module, you can have the embedded go run time, you can instantiate it against its run time, you can pick off that lifted transform method and embed it as an export. And so the component model then subsumes all this JS glue. And so instead of having all this glue, we can now have web assembly components, which internally do all their own linkage setup. And the flip side of that is in solving for embeddability, we also get first class wasm execution environments. So the ability for wasm table to do its own instantiations and manage its own kind of hooks and life cycles. And from a registry perspective, we get the MPM registry with JavaScript modules interacting with web assembly. On the log registry, we can now have web assembly modules as first class embeddable modules that can run in different environments. And when we want to embed components in the MPM registry, we can possibly even have cross linkage workflows and things like this that might develop in future, so that you can actually lean on kind of cross registry wasm embedding. So anyway, this talk is about the JavaScript tool chain. So what is the JavaScript tool chain? We have the following tools. So jQuery transpile and the idea of jQuery transpile is something like take a component and convert it into a module that has the same interface as a JavaScript module. So you just convert a component and you get an ES module that you can import and get the same interface for it. You can also do custom instantiations and have more customizability, but jQuery transpile is this main command. Componentized JS is the ability to host JavaScript inside of components. So where transpilation of a component allows you to embed components in the JavaScript ecosystem. Componentized JS allows you to take JavaScript applications, embed them inside of WebAssembly components and run them in other ecosystems. So you actually embed the entire runtime. And preview two shims is an implementation of WASI preview two for JavaScript that works in browsers and Node.js and should hopefully work in other platforms eventually. So the last thing we also have is a bunch of APIs for JCO. So JCO can actually also be used as an API to get access to the transpilation. For example, in a build plug-in for VARLA, for VIT or something, it can be used as a dependency and it can be also used to get access to a lot of the component model tooling which is exposed in a way that can be easily used in JavaScript. So that's the motivation. I'm now going to jump straight into demos. So the demo that I've chosen to do today is just this fun one and please don't read too much into it, which is commands in the browser. So you were running CLI applications in the browser. And if you want to see what the VS Code team did with us, you can go to Dirk's talk tomorrow. But in this example, I've got an environment in the browser that has an embedded file system. I can use some basic commands to see the files and read these files. And I've also got access to some CLIs like WASIN tools CLI. So I can actually use WASIN tools to print. I've got a dummy component here. So I can say WASIN tools print. And it'll run WASIN tools in the browser and print that component. So I've got all these sort of things running. And what I'm going to try and convince you is that this is incredibly easy to do with components when you have these derivatives because everything's just running on the same WASI subsystem and everything can just be compiled as a command and run in the browser and transpiled. So to demonstrate that, let me show you an example of how I can build something to run in this app. So I was looking to see if I could find like a really simple like kaosay kind of thing and I searched on crates.io and I found this thing called charasay. So I was like okay cool let me try and build this and run it in the browser. So I can do cargo build target WASIN 32 WASI and build it for release. So it's just a WASI build and then this is where I would normally for the component mod I would do WASIN tools component new and I would build this component into a command component. I always hate locating the adapters so I have a wrapper for it in jaco so I'm just going to use jco new and I'm going to use the flag WASI command and then just point it at this target WASIN 32 WASI release of chara and we're going to output this as a chara.wasin component. So this is building it into the command component and now I'm going to go back to my command app here and in the browser I haven't refreshed the page I can sort of install chara to this chara.wasin. I never got around to doing insertions in the CLI so apologies but it's actually the commands chara.wasin here so I'm going to install that and hopefully it'll work where I can do chara say hello components and so I was able to install I was able to build a Rust application for the browser and load it into the page without refreshing in the same virtual machine because it's all just running on the same WASI so it's like it's a really nice abstraction you can do some cool stuff with it. Actually what I meant to show with this demo is actually that I could first use jco to test it so we have a jco run command as well which will do the same thing run things in the CLI and I can also do jco run chara.wasin and then say hello components and jco itself is running in Node.js and so this will then be running it on top of the Node.js APIs and it's using Node.js as a representation of all the WASI APIs you're getting the Node.js basically the Node.js host as if you were just on the sort of POSIX machine. So something went wrong. It's in this folder. This is the actual component and then I get the get it running in Node.js. So that's WASI commands and they're really fun. It's a great thing but as I said this is demo material. Don't read too much into it. But the interesting part is what's going on. So this is all running in this kind of a module shell where I've got the main terminals all running on Xterm. So that does all the heavy lifting in terms of providing a terminal in the browser and then I've just wrapped it with literally copy paste or stack overflow to like make it a rebel. And then the main guts of the application is the shell reactor component. So the shell is itself written in Rust, the actual shell of the application and this is transpiled with jco to run in the browser. And then what I'm doing is have this create terminal command that's able to take a line from the terminal and then it just pipes it into the shell and tells the shell to run it. So it's just a basic kind of repo loop. And the last thing I have to do is pipe the standard out and standard error from the sort of base WASI into that terminal so that it displays everything into the screen. Right. And then inside of that shell reactor component I have all of my my tools available, which are running on top of this preview two shims implementation that's running in the browser. And yeah, that's that's really what that's all the pieces and how they fit together. So let me go into that reactor and show you how that is how that works. So to do this, what I'm going to do is go back to a like a simpler version of the shell. And in this example, I've got this this actually first just to show you that the demo is actually, as I said, it was here's the HTML I'm loading X term. I've got an import map that's mapping by code lines preview two shims in the browser. It's just installed in node modules. It just makes it easy so I don't have a build step. And then I've got my terminal. I've got my shell being loaded. And from the IO of preview two, I'm setting the standard and standard error streams to pipe into the terminal. And so I'm calling shell that in it on startup and on each line, I'm calling shell that execute. So that's that's everything that's running in the page. And so the shell is this Rust application here, where it's implemented as a component and implements the in it and execute methods and then just has some some bare bones code to do that. So the reason why this is a reactor and not a command is because whereas a command has a run function that runs from end and has the sort of standard POSIX primitives, a reactor can be more like a library and it doesn't have to be toned down when it's finished, it can sort of continue to exist and you can have these commands that can be called again. So the build for reactor is very much the same. You do a target build for wasn't 32 as a I'm just going to do a debug build for this one. And I'm going to use my J Courtney again because I hate locating the adapter for demos, which is a WASI reactor. And I'm going to convert that target wasn't 32 WASI component of shell.wasm in the debug folder into a shell.wasm component. And then I'm going to use this is where I now need to show you jQuery transpiles. So previously, everything was happening in the browser. It was all wrapped up magically. So I could just load these these commands into the browser. But to get the from the Web assembly to the JavaScript, I'm using jQuery transpiles. I'm going to take the shell component that I just made. I'm going to transpile it into the equivalent JavaScript. So shell jQuery transpiles shell.wasm. And I'm going to output it into the lib folder. And that will go ahead and basically build up all of the glue codes. I've got lib shell.js, which represents that component module. And it automatically has WASI dependence where I've used things like FS or I've used things like print line. It'll know to use the WASI functions for it because I built the WASI version. It also has the types included so that if you're importing this in a JavaScript application, you can get good typing when you're using the application. So that's in lib shell. And I can then, in this demo, just load that lib shell. And so that's really all it is. The rest of it is just running on a local server. So when I go back and refresh this, I don't have any of my fancy commands now, but I've just got like that basic echo from that application. And so it's just running this very simple shell application. So yeah, I will go a step further since the demo seems to be working. I told you there were a lot of demos. We haven't even begun to get started. This is where I'm going fast. So this skips out the whole step of like how I got was until it was working in the browser. Right. So I've just got this reactor. Great. But I'm not showing any component linkage. So if I want to have other commands, like I was able to like create an echo here and it works. And I could do the same sort of technique for other commands, but I really want to be building in other codes. So I don't just want this the single shell component. I want to be calling out to other components that I can run. For example, when I had my I was able to do wasm tools and print out a binary. So I'm going to build in wasm tools into this component as well. So the way the way we do that is we have a with definition of the shell interface where we've got these this init and execute that defines the reactor. And I'm going to update this to add an import to wasm tools, which was a component I created earlier. So I have available a wasm tools component that say I got from the wild registry or something. And for this demo, I'm not doing full registry integration because I want to show the fine grained linkage in the JavaScript ecosystem. So I've located it in my width folder at the depths folder. And it's wasm tools, wasm tools.wit. And I've got this nice wasm tools component that makes available all of the wasm tools interfaces for me to use in a way that I can embed in any component environment. So I'm going to add this as an import to this word file and say import the wasm tools. And it's called the tools interface. And this will now give me access to that component inside of my Rust application. And to use it, I will do the use create local wasm tools tools. And that will give me that interface from the component. And now I can write my wasm tools command in my application. So again, this is all demo material. So I'm not going to do proper error checking, et cetera, right now. But let's just see if we can write a wasm tools print and see if we can get that to work. All right. So for a print command, what I need to do is I first need to read the file that's being printed. So I'm going to read the bytes using the read file interface. And I'm going to read from the argument that's parsed. And then I'm just going to unwrap that because I'm not going to do error handling for today. I can now call my tools print method, which will take those bytes as a slice, print them and return the output. And I'm going to print that to the console. And again, I need to handle errors on that because the component interface for print in wasm tools will actually return a result. So that's where it's using first class for us to result. And that's it. So I can now build this application for go through the same build steps, create our reactor, and then do the transpile step. And now if I refresh the demo, I should have an error. Great. So OK, we've got an error in the console. And if you look at this error, this is that it can't locate the wasm tools because it's locating it from local wasm tools for its tools, which doesn't exist. And the reason why was because I didn't include wasm tools in my component build. So what I'm going to do is show you how I can use linking in the browser to get access to that tool. So separately, I don't know why I did this so much demo material in this talk. It's not a good idea. But separately, I have wasm tools over here. Here's the component wasm tools.component.wasm. And I've jQuery transpiled it. So jQuery transpile wasm tools or wasm tools. And that's put it there as JavaScript. So can I link this version that I've just transpiled off of my shell to this version that I just transpiled of wasm tools? And to do that, I can use a feature in transpiled called map. So when I transpiled the shell component, I can map what's local wasm tools forward slash tools. And I can map it to, as a JavaScript module, it's going to be in the shell lib folder. So I need to backtrack down to the shell folder, then backtrack down to the folder below, go into my reactors folder and then go into my wasm tools folder. And then it's going to be wasm tools.component.js. So that'll tell it how to find it. And now if I run that, it'll find the module. So it's just loaded it in the browser. But now it gives me a new error. This requested module does not provide an export name print. And the reason for this is that when you have, when I imported wasm tools over here, I imported the tools interface. I did not import the implementation that was provided by the component of the wasm tools reactor, which itself has an interface tools that is exported as a tools export. So what I have to do is I have to map my print interface that's being imported into the tools export interface of the wasm tools component and its print method. And so I'm going to update my mapping here to rather map into the tools and to just illustrate that exactly, let me actually just open up the folder that's being output by the JS module system here. So it's loading print from this wasm tools component, which is just a function export. But it's supposed to be off the tools interface. So I can use this hash in the map, which is going to direct it to the tools interface. And when I do that, I import the tools interface and then I get the print method off the tools interface. And if I refresh that, I now finally have an application working. That was the hardest part of the demo. So we've got through that. We've got through the hardest thing that you'll have to see today. So thank you for bearing with me. And now I can print my wasm, I've got wasm tools running in the browser. So that's an example of how you can take another component, link it in dynamically. And this is dynamic component linking in the browser. And you can kind of have this interrupt between the components in the JavaScript ecosystem. Normally you would use Peter Huynes, how do you say a second name? Peter Huynes cargo component project. And cargo component will do all of the linking for you and battle everything together. But in this case, I wanted to just show that dynamic linking so you could see how it works in the browser. If I want to recreate that kind of composition model, I can use wasm tools compose. So the way that we would, so in the shell, let me just show on the network tab. It's loading in the wasm tools component and then it's loading in from the shell, it's seeing the dependency on the wasm tools component and loading in wasm tools, which is then loading in all of the wasm files and executing in the browser. If I wanted to do everything in a single component, I can use wasm tools compose. And wasm tools compose will take that sort of direct linkage between shell and wasm tools and turn it into a single component that represents both. So I can say wasm tools compose and I can go for the shell.wasm, which is the original shell, compose it with the definition of wasm tools in the wasm tools reactor, which is in reactors wasm tools and I'll put that as shell.compose.wasm. The shell.compose.wasm now has wasm tools in line. It's still passing through to all of the wasm interfaces which are separate. And I can then transpile that shell.compose.wasm. I'll transpile it out to the lib folder again. And this time I don't need to do any mapping because it's included the wasm tools component inside of it. So it was a single component that had wasm tools and the shell and I've transpiled it all in a single operation as shell.compose.js. So if I update my demo to instead load from shell.compose.js, I'll get the same thing running, but it's not separately loading wasm tools. It's now loading it all in a single component that bundled them both together. And it's still able to do the print using that same implementation running in the browser. So now the composed wasm. So you can see that the component model actually has these composition semantics through the first-last instantiation and starting linkage and you can have these different kind of linkage scenarios. So complex to show, but I really wanted to just get it down and go through that because I think it's, you have to see it to kind of get a picture for it. And so I hope that helps and luckily we got there in the end. So yeah, this is what we're looking at. We have the shell reactor component loading from wasm tools and any other commands. And these are all running as separate wasm components and you can use wasm tools.compose to get a single component. So you can either run them separately and transpile them with the browser, use wasm tools.compose, get a single thing and run in the browser. And so you get these graphs of applications. We can have JS modules interacting with these WebAssembly components. And in this kind of transpilation operation, we're getting graphs of JS and WebAssembly. And it's still just glue. It's still just glue being generated, but it's glue with a future lowering. And so this is the first class static semantics of the component model. I mean, you have something that you'll build to link and reason about and you can do cross wasm optimizations, et cetera. Right. So next thing I want to talk about a little bit is the WASI linking, which is the other piece of this picture. I'm just implicitly linking against WASI that it's running in the browser, an instance of WASI running in the browser. And this is, it's almost like there is a single WASI implementation against which everything can link, which represents that same machine. And it's just another import. And it's sort of like an ambient import. There's no ceremony because it can just be loaded from the node modules or through your standard resolution when you're running in JS environments. At the same time, you can create in JS custom WASI instances as well. So this is where you get in your JS embedding the choice between virtual platform layering or sort of direct host usage. You can create these different linking models. In node JS, it actually has an implementation of WASI that's running on core wasm. And this node JS WASI is available as a core module that you can import from node colon WASI. So I mean that any JS module in the MPM ecosystem can import node colon WASI. But it doesn't support this shared ambient linkage. You have to actually instantiate it every time because of the shared memory properties. And so with the benefit of the preview two model is we can have this ambient shared WASI where lots of modules like can just link against the same WASI instance and be able to be able to share the same file system where they want. And you can define those boundaries by these instancing of the actual underlying WASI implementation. So it's looking like we should be able to provide a preview two and node JS something like this where you could actually just import standard out and write to standard out in node which is exactly how this terminal is running and how I was able to run everything without any other build step because a new way to find the standard out. And alongside this ambient mode we will still provide instancing. So you can create custom instances of WASI that represent virtual machines. All right, so that's jQuery transpile and WASI. The componentized JS project is the, just seeing how I'm doing for time. Yeah, I think we're all right for time. So componentized JS is the other side of this which is saying we want to take JavaScript we want to embed it in other component environments. And so it's a project that allows you to write components as JavaScript modules that you can then build and package up and embeds a spider monkey. So it's actually a browser embedding that's useful for sort of embedding environments where you want to make JavaScript available as a language. For example, you could target any world. So if you wanted to write a CLI tool in JavaScript you could target this WASI CLI run world or WASI command world on WASI CLI run and you can create a simple command. Now I'm going to keep the componentized JS demo relatively simple so that we're not going to get too much into the demo weeds again. But what I'm going to do is show an example of taking that same shell that we were just dealing with and saying well instead of writing it in Rust could I write that shell in JavaScript? So I have the same world that I'm targeting which has the shell interface and an execute function going to write in JavaScript and then using componentized JS to get a component that represents that same shell. So let me just show you that and hopefully with some luck it'll work out as well. So let's take a look at the wood again for the shell and I'm going to remove the WASI tools import because we're going to skip that out for now. So I've got this shell interface with two functions in it and execute. They both return a result. In JavaScript top-level results are treated as errors so we could just implement them as normal functions. So I'm going to write a shell.js and create that interface and add the init method and the execute line method. And for the execute line method let's just do a simple echo again. So we're going to get the args as the line splitting on a space and then we're going to switch on the args and if it's an echo we can just log it using console.log. So to use componentized JS I'm going to use jcos componentized command which is a wrapper around componentized JS so componentize. You would normally install them both from NPM they're JS native tools and I'm going to point it at the shell.js and then point it at the width from our shell application because we're using the same width and that's going to output my shell.js to WASM. There's one other thing I need I forgot to add to the componentized command which is I need to explicitly enable standard out because by default it doesn't assume arbitrary capabilities. So let's run that. And then I can do the same step with jco.transpiles so I've got this shell.js.wasm and I'm going to transpile it out and I'm going to put in the same shell.lib folder just for convenience. So that's shelllib.shell.js.js so let me update to shell.js.js and let's check our demo. So I don't have any of the other commands but I'm running JavaScript in spider monkey in the browser and I've got my echo command, right? So all right, one more demo and then we're there. So yeah, thanks for wearing with me. I'm going to show you WASI vert next which is all of the time I'm using preview two shims which is a browser implementation of WASI. Instead I'm going to use WASI vert which is a WASM first implementation of WASI. So you can basically instead of running on the WASI that's in the browser we can actually build that WASI implementation itself in and then all we need to depend on is the standard out basically because we can actually bring the file system and all these things up into the virtualization layer and this is the sort of virtual platform layering story and this is just a very, very simple demo. There's a lot of like much more exciting things you can do with this but I'll just show you a very simple demo against the last component we wrote. So what I'm going to do with this just to demonstrate it really simply is load that shell width that we're writing to again and this time I'm going to add a WASI import because WASI is always available I don't need to do anything special to locate it. So I'm going to import a WASI CLI and the environment interface which is environment variables. So this gives access to environment variables and then in this JS application that I'm building to that world I'm now able to import from the environment interface which is WASI CLI environment. So I've got access to this get environment which is the sort of POSX primitive. In my inner function I'm going to call get environment. Unfortunately we don't yet have support for first-class objects so I need to use object.fromentries to turn the key value list into an actual JS object and this is going to give me a mutable environment variable in the local scope which the execute function can always check and access which will have all the environment variables. Now I can update my echo command to do replacements I want to replace my environment variables. I can do a JavaScript reject so if it's a dollar and environment variable we're going to replace it with the, look it up in the environment object and if it's not found we'll just return it originally and I need to add a slice one there because we don't want the dollar and that should do it. So let's run through the commands again which was componentize and that'll give me the shell.js that I can now run in my shell. Now to set environment variable say I had a production environment variable so it's an application that was using environment variables and I want to set them, I can use wazvert. So I've got this existing shell.js.wazm component that I can run anywhere and it's going to read some environment variables. Let's use wazvert to set some environment variables in that component before we even embed it. So with wazvert I can say set environment variable say we just want to say production is one and I'm going to apply this virtualization to that shell.js.wazm file and I'm going to output it as shell.js.wazm. So this is the JS engine running the JS code now wrapped in a virtualization setting the environment variables that it was accessing the environment variables from and now let's transpile that with jQuery transpiles shell.js.wazm, I'll put that into the shell.lib folder and update the demo to access shell.js.wazm or transpile. Thank you. Something looks wrong here. Well, maybe it's right. We'll try it. And so I have my my echo command which is not working. Damn it. It's always always a chance of that happening. So I'm componentizing with standard out enabled and I'm verting shell.js.wazm into shell.js.vert.wazm and transpiling that into shell.lib. Yeah, this looks wrong. What's happening? Oh man, the demo gods are not serving me well today. Let's have a look at the console and see if we're getting anything. Nothing at all. Oh my gosh. Oh man. Okay, well let's just pretend that worked, shall we? We got 90% of the way. I did warn you that there was a good chance that something was gonna go wrong. But it does work, I promise you, but I won't go through live debugging right now. Worked every time that I went through this. But yeah, so with waz.vert, we're able to take this application and we're able to actually bring in parts of the wazi implementations into the virtualized version of the component that we can then embed again. So yeah, those are the various pieces. And so today it's just end and FS support for being able to mount a file system, managing environment variables. But there's a lot of options for flexible virtualization here where you can have fully functional virtual hosts being embedded. The last thing I wanna talk about very briefly is dynamic web applications, operations. And that was actually the thing in the original component that when I was showing the dynamic loading of commands into the browser, I was able to do that, was writing some custom resources that are able to interact with the browser world. So there's some really interesting ways in which you can open up the browser functionality and waz.mbind.gen has this web syscrate which has high level operations working with the web. You can go very far with this using wasm resources which represents sort of class like semantics for working with objects. And the example here that I was using for loading components dynamically was this is how I was putting that together. So I had a component resource where I was able to actually dynamically instantiate this resource inside of the browser, dynamically loaded with some JS, but sort of coordinate that from the WebAssembly component side. And the execute function, if it returned a component, we would then separately call this execute component something like a sort of a resume approach to running that command component. And that's how I was able to achieve that. I would love to show you some more demos but I am all demoed out after doing that today. So if you're interested in seeing more of this in action and using these tools, come along to the component size JS event on Friday, please try it out. And if you haven't signed up for the event yet, you can find it on Eventbrite if you search for component size. So anything that'll come up for that keyword. And I look forward to seeing you there or otherwise on GitHub. So thanks very much. Here's the project links that you can try out. Cool.