 I'm pretty happy to be here to start talking to you about why you should consider running JavaScript inside WebAssembly. So my name is Angel, I'm a staff engineer in the WebAssembly team inside the VMware AI Labs. Today I'm here with Saul Cabrera, unfortunately he couldn't make it to come to the conference so instead of having him directly make it load, we'll have Virtaal Saul with us. So he will help me with all the presentation. Saul is a staff engineer working at Shopify team, he's especially working on the Shopify functions project in which they allow you to extend their Shopify platform with custom code. He will talk a bit more about it. But before starting with the specific use cases, let's talk a little bit about JavaScript and WebAssembly. So before actually starting with that, I would like to do a quick survey. So who of you raised your hand, please, are familiar with WebAssembly, okay, that's cool. How many of you actually use it in the past? Okay, that's good. So basically WebAssembly is an open standard that defines a binary structure format for a virtual machine. What it means, all these words in reality is that you have different application, different programming languages like C, Go, Rust, C, among others, that you can actually compile. But instead of compiling it to a specific architecture and operating system like Linux and V64, you compile it to WebAssembly. So you get a specific binary that kind of runs anywhere that you provide a WebAssembly runtime. Or WebAssembly, if you're watching. These sounds may sound weird because, I mean, I also came from the JavaScript world, from a full stack, and I think I used to work with dynamic languages and interpreted languages, so I didn't know anything about compilation, more than using Webpack and different kind of bundlers. But this is how, in other cases, when we wanted to run native binaries, for example, in Windows, Linux, we actually needed to compile the code and then run it directly. The thing is that, when I say it runs anywhere, when we have our WebAssembly runtimes, these include browsers, which is very familiar to us. We have different kind of browsers that supports or includes our WebAssembly runtime, like Chrome and V8, Mozilla, Firefox, and SpiderMonkey, and all those allows you to run these kind of applications. And how you actually access to those applications, how you start the WebAssembly models using JavaScript, which is the actual code that allows you to load the WebAssembly model, load it to the browser, and start running it. Based on the specific architecture, this happens, like, years ago, when they started implementing WebAssembly, and it helped developers to develop applications, like Figma, for example, which started as one of the main applications using WebAssembly intensively. And they also helped to port existing applications to the browser. So we have today Adobe Photoshop in the browser, we have Google Earth, and instead of having to create everything from scratch in JavaScript, they could take their own databases, compile them to an assembly, if they're doing slight changes, and then running it directly in the browser. So WebAssembly opens the possibilities to run this kind of code, like C++ code, in the browser without having to deal with transformation steps and things like that. So this is the curriculum structure that we have, which is basically we have a browser that runs JavaScript, that loads to WebAssembly runtime, sorry, WebAssembly model, runs application, gets everything. And what I'm talking to you here is to actually run JavaScript inside that specific WebAssembly model, which could be something like in which level of inception we are, like running it stop inside of a stop, can't even go a step further. But the key part or the key thing of this specific talk is that this is just one example of where you can run WebAssembly. But note everything, it's inside the browser. You can actually run WebAssembly in many different environments. Like, for example, in another center or in a cloud running a negative server, you can do it inside a mobile phone directly in your application, like using an Android or iOS. You can run it in an embedded device or in IoT devices. So just to get you an idea about why JavaScript may start making sense to run it inside WebAssembly. And why? Why is so important? This is something that I have been noticing in many different projects that uses WebAssembly as a conditional technology. And it's that a lot of things wants to support JavaScript inside. Why? Because everyone, not everyone at all, but many, many people knows about JavaScript. From very new developers to very experienced ones. So anytime your project supports WebAssembly, you have already a huge community of developers that understand how to use your project. So this is where the real value of running JavaScript inside WebAssembly start making shape and start making sense. We can consider that JavaScript is an universal language. This is a famous quote from Jeff Atwood about that any application that can run in WebAssembly in JavaScript will eventually be written in JavaScript. So we have the use cases about the browser, which is pretty full for WebAssembly where it actually started. But it opens a new set of possibilities for running JavaScript in many other environments that before wasn't supposed to. And here is where we are going to talk specifically about the use case of Shopify and why they use WebAssembly at JavaScript to extend their own platform. And for this, it's the tool for subtle. Thanks for having me. So in this section, we're going to talk about extending Shopify with WebAssembly. And in the next section, we're going to talk about how JavaScript on WebAssembly works. In return, instead of why we have adopted WebAssembly at Shopify, it's important to take a look at our use case. And our use case is extensibility. We can think of extensibility as opening one part of your system to execute untrusted third-party code. In order to understand a bit more how extensibility works in the context of Shopify, let's take a look at the personas involved in this process. So at the center of everything, we have Shopify, Shopify's infrastructure. And the first persona is the buyer. The buyer is someone that is looking to buy physical or diesel goods online. The second persona is the merchant. The merchant is the persona who's responsible for selling this physical or diesel goods online. Then the third persona is the third-party developer. Whose responsibility is to extend Shopify through an app that doesn't have to run in Shopify's infrastructure or through a function, what we call Shopify functions, which is the main driver for extensibility. This whole idea of extensibility means enabling more complex interactions in the relationship between the buyer and merchant. Shopify has all the information to enable these complex interactions, but it wouldn't be scalable if Shopify had to deal with all the combinations of how these interactions could go around. And by complex interactions, I mean, for example, calculating a discount. Or there are some discounts that are very simple, but there are ones that can get very complex. For example, giving you a discount for your export on a particular store. Or giving you a discount because your particular user on that store has a particular tag. As I said before, Shopify has all the information to calculate this, but it's easier, more scalable, and definitely more friendly to the merchant to let them upload a script or a function that is going to allow them to write this business logic on their own because it's easier to change and it's easier to scale through time. It's important to note that these interactions must be calculated in a synchronous and a secure way. Synchronous because most of the time, these extensibility mechanisms run inline in a checkout. Why inline? Because for example, at this camp, we cannot afford to calculate at this camp once the checkout has gone through. So it's important to make sure that we can make these extensibility extensions in a synchronous and in a fast way. And secure because we're dealing with third party code and by the nature of third party code it's really unsafe all the time. And here's where WebAssembly comes into play. When we first adopted WebAssembly, only system-novel tool chains were targeting it. Like for example, C or C++ or Rust. And this all is great, but the challenge that comes with these tool chains, only these tool chains supporting WebAssembly is that there's a question of adoption. What happens with all the other tool chains like JavaScript will be better and sure, more app-friendly? For a platform that is betting WebAssembly, these questions inevitably come around and we have to answer them. And so here is where JavaScript on WebAssembly came to be a topic that we eventually invested on. So before digging into how we made JavaScript on the work, I'm going to give a brief walkthrough on how JavaScript on WebAssembly, sorry, on how JavaScript engines work overall without them being embedded on WebAssembly. So this JavaScript engine model, they have a one-term environment that contains a GC that contain other built-in functions that contain most of the API that is exposed to the older person that we are used to working with. Then in the compilation side of things, these engines have a multi-tier compilation pipelines and the first step in the compilation pipeline is interpreting. So the interpreter is going to grab the source code and then start interpreting it. Once it has enough information to improve the execution, it's going to enter in the first baseline just in time compiler, which is going to output machine code. Not as optimized, but it's already faster than what the interpreter can do. And the next step is an optimizing chip, which is going to grab that bytecode that was fed into the interpreter and optimize it even further than the baseline just in time compiler. Meaning that the code that is being outputted here is going to be way, way more optimized than the baseline chip tier one. And so here, this is how the full picture ends up working. So we have the source, then we have the compilation tier, then it gets to machine code and then that machine code interacts in some form or another with your entire environment. Now, when we translate this to WebAssembly, there are a couple of things that we cannot do because these are not limitations. These are features of WebAssembly, call it somehow. And the main features here is that we cannot generate code at runtime. So what jits do is that they, at runtime, when your program is executing, they generate new code that gets swapped in and then that code gets executed. By default, we cannot do this on WebAssembly due to security purposes. So if you wanna do any of this type of thing, which is in WebAssembly, everything has to do, everything has to be ahead of time. And so the best that we can do here, for example, is grab the interpreter, grab the runtime and then compile that to WebAssembly. So this is what we would have, for example, we would have a source in which we would interpret and the interpreter obviously has access to the runtime environment. So the best that we can do here is interpretation. You may think, well, this is going to be slow. Yes, it's going to be slow if you compare it to native execution, although there are some techniques that are starting to surface right now that might enable us to do full out of time compilation of JavaScript, taking advantage of its basic tiers. And so what I want to depict with this here is that when we have WebAssembly module of a JavaScript and you compile the WebAssembly with a particular program, we have the runtime environment and we have the interpreter. So the runtime environment is what I already explained and the interpreter is the dynamic piece that is going to interpret whatever code you give them. So one thing to note here is that the runtime environment is going to be static. Nothing changes there because it's only giving the interpreter access to JavaScript APIs, for example, or JavaScript collection, that's something that you have enabled. But usually when running JavaScript in WebAssembly, we disable any JavaScript collection because the module is going to get dropped at the end of an execution, basically collecting all the memory that has been allocated in that particular module. But the important thing here is that this runtime environment is constant. So we can do some head-of-time optimization with it, which we're going to see next. So we have this WebAssembly module that contains a particular execution piece, which is the interpreter, the dynamic piece of the particular module, and then we can generate a snapshot out of time that's going to generate a new WebAssembly module in which the constant part has been fully optimized out of time so that when this WebAssembly module gets executed at runtime, we don't have to initialize the engine over and over, meaning that we don't have to pay that price of doing that concept work when your module gets uploaded to whatever infrastructure you're running into. So in this model, this specific execution is going to be faster than if we had to execute the engine initialization all the time, the constant part, every time. In fact, there is a very good article in the Bicolines blog, called Making JavaScript Run Fasting WebAssembly, where it explains all the technicalities of how this is done through this tool called Wiser, which is a Bicolines project. And you can read it there. At the end, we're going to have some QR codes with all the links that we have in this presentation if you're curious. So thank you very much for everything that he mentioned. This is the kind of internals about how this works, that in reality, when we talk about running JavaScript in WebAssembly, it means that you actually need to compile a specific JavaScript runtime in the WebAssembly module and then it will run the code on top of it. For this specific thing, compilation of JavaScript runtimes is not something that is trivial and that people that are used to work with JavaScript is not an easy thing, actually. You need to understand how to compile C code in this case, where it's a quick yes, which is a pretty small JavaScript runtime. So for simplifying all the systems and just getting your code running on top of JavaScript runtime, we have the concept of Java. So Java is a project created by Shopify, the knowledge part of another organization, which is called Micronoliance, that allows you to compare JavaScript source code directly into WebAssembly module that will include not only your source code, but the actual JavaScript runtime compile internally. It's super easy to use, it's a super nice user experience and this is kind of the first iteration that Shopify did to simplify how developers can extend their new service or Shopify functions using JavaScript on top of WebAssembly. So for this, we have a demo. Now, I'm going to show how Java and JavaScript developers have been teaching works. Here, I have a pretty simple index.java file, which, if it works as expected, once we execute this, it should print Hello World to the console. Before compiling any of this to WebAssembly, I'm going to give you a brief walkthrough on how Wiser works inside Java. Here, we have a raw straight that is exporting a wiser.initialize function. So when this raw straight gets compiled to WebAssembly, we're going to get a WebAssembly module that is going to export this wiser.initialize function. And this initialize function we're doing is initialize from the runtime, which is putjs. That's the runtime that Java uses internally. And evaluating the JavaScript source code and converting that into bytecode. And then we have a main function that is the function that's actually going to get executed once this module gets to run. So once we run this module, we won't repeat the wiser.initialize that it actually will get removed. And then once we hit run, or we execute this in wasn't time, the only pieces that are going to be executed are the parts on the main function. If you can see in the main function, we already have the bytecode ready and the runtime already initialized. So the only thing that's left to do is actually call run bytecode, which is going to interpret all the bytecode that we have already preprocessed. And by preprocessing, we have already parsed the source and we have already converted that into bytecode and our engine is already initialized. So all that, we save all that processing by doing it ahead of time. Going back to our small script. If I open a terminal and I run javi compile and pass it in the index of JavaScript file and then instruct it to create an index of wasn't. It's going to take some while and then it's going to give us an index of wasn't file. Now we can run this to wasn't time and instruct it to run the start function because all javi modules are was compatible. The start function is what gets exposed when you're creating an executable for wasi. Once we do that, we should see hello world. So based on this demo, this is the final user experience that the Shopify teams wanted to give their developers that they just need to write the JavaScript code that they want, then combine it to WebAssembly using javi and that's all. You don't need to take care about any compilation step for the runtime. All the things that you saw in Rust is the javi code but as a developer, you don't need to check it anymore. You just don't load binary that will create the wasn't file and this is the actual function that you upload to the Shopify. The second project that I wanted to demo today is called was a worker server and it allows you to develop serverless applications and run it basically anywhere. It can run in many different environments thanks to this portability from WebAssembly. The thing about this project and why we wanted to highlight here is that the same approach that we are having with JavaScript in which you combine interpreter and can't run JavaScript code in different environments allows you to repeat the process in all the languages like Ruby, Python, if you follow the same example you will be having the same situation. You can have Python code running with WebAssembly in many different environments in which before you couldn't do that. With this specific example that I'm going to show you you can even combine them together so you can develop applications that take advantage of the different ecosystems. You can write some part of the application in Python and other part in JavaScript go to the different libraries that you need and then you run all of them together to create more complex applications. So for this example you can see it. So just to give you a brief introduction about was a worker server how it works is that it reads the files inside a specific folder and based on the file name it will create APIM points directly that you can access in your browser or any tool that you want. This is called file system routing and it's something that another project's like Eleventy for example uses so it's a very common pattern that we found very interesting for this project. So here in this case we have JavaScript.js Python.py and Rust.wasm. We have different source code actually the wasm model is based on Rust so all of them will run inside the same application together using wasm worker server. So just to give you a brief visual about what's inside the specific files this is the source code of the .js file. It's just a reply function that basically checks the method that in this case just if it's a portion of it it creates a basic HTML code it could be a different file and from now we're just putting everything inside and inside the code we are just getting methods, some headers the body that you passed on it and then create a response add some specific headers and then return it that's all that we need. If we see the Python code in this specific case it's something pretty similar we also produce this an example but in Python. For that we created an infunction for worker here we have pretty similar code in which we get the method, the host we get all the information from the request we create a response put the header and then return the response but this could be a completely different application using a specific libraries whatever you need for this specific endpoint. So this is the way to install wasm worker server it has a single command I have already installed so I'm going to install it again. We see it's already there. So now I get into the app folder run it directly and it automatically picks all the different files written in completely different languages and then expose them as an endpoint. So if we go here and open it, it works. So here we have the hello world directly. And you can see that it's flying everything is running inside the web assembly it's totally sandboxed it's using JavaScript. Oops, the things that I'm going to see the close is going to be difficult. Okay, so now if I go here again I'm going for example, the five from one, same example. And we are running everything together without having to deal with interpreters you don't need to install anything yet wasm worker server and then you get directly access to all this ecosystem and all this programming languages. Yep, and that's all that I have to tell you today. I think we have maybe one minute for questions. Okay. Okay, so the question it's about in this talk we also show some Rust code. So what's with the relationship between JavaScript and that part of the code? So the Rust code that we show before is actually the Java tooling. So this kind of example that under the hood many of these tools that interact with web assembly use Rust because of the compatibility that it has with the ecosystem. But that's only from the point of view of the tooling itself. Once you have that tool compiled which is what developers finally don't load you don't need to touch Rust if you don't. Exactly for the specific case, yeah for the specific case of Javi is basically running and converting JavaScript on web assembly. But for example, for the wasm worker server it works more or less under the hood so you get basically the interpreters compile and then you put the code on top of that. For example, the Python interpreter is based on sync code, not in Rust. But we compile ready for you so you don't need to do that compilation process which is something that is not trivial for everything. Even for me, I mean to me a while to set up the environment and the compilation. Basically you can have different servers and different languages but then when they compile they'll communicate in JavaScript. So you can go down to browser or you could get, you could then have your Rust API speak to your compiler into JavaScript. Is that correct? So part, yeah part is totally correct. And it's one of the biggest value proposition for web assembly. Once you compile a project to web assembly that it could be using Javi from JavaScript to web assembly or using Rust, C or any of these languages. What you get finally is a wasm model which is basically a little destruction compiler. So those models can interact together meaning that if you have those proper APIs defined between each other you can invoke one specific function from a JavaScript source code calling a specific Python method in another model. So that's part of what is under developer which is, it's a proposal called the component model for web assembly and it allows you to do exactly that. Interoperate between different languages altogether at the web assembly level. And for the memory of the whole of when it's compiled I'm understanding it's very, it's like it doesn't take up too much memory. That's also another very interesting thing about web assembly. So one of the things that we did with wasm is to compare how for example we have the Python interpreter which is the one that it was used by wasm worker server to run that Python code in the example and it's only the Python interpreter combined to web assembly. So it's about 18 megabytes I think because it includes the standard library of Python. If you compare that to the minimum or the minimal container that you can import for Python it's almost double in size. So this is something interesting also about web assembly that you get right, you get only your source code combined to web assembly and that's your model. So it means that it reduces a lot of things when distributing models in faster and cheaper. Exactly, it's true that faster depends in the case because for example what Saul mentioned is that in a regular JavaScript interpreter like V8 or SpiderMonkey there are a lot of mutations that happen during runtime. So all these did combine and everything. So if depending on the specific case more complete interpreters come in for optimization that can make the code run faster. But in theory all the models that we're doing in the assembly are smaller. So it's kind of globing them, it's practically instant. Oh thank you, that's a good talk. Thank you. Thank you.