Web Assembly (Wasm)

Creating an AssemblyScript Wasm Loader

Jem Young

Jem Young

Web Assembly (Wasm)

Check out a free preview of the full Web Assembly (Wasm) course

The "Creating an AssemblyScript Wasm Loader" Lesson is part of the full, Web Assembly (Wasm) course featured in this preview video. Here's what you'd learn in this lesson:

Jem codes a utility class that will use the fetch method to load a wasm file in the browser and return an instance for the compiled Web Assembly code. A fallback method is also created to for browsers that do not support Web Assembly's instantiateStreaming method.


Transcript from the "Creating an AssemblyScript Wasm Loader" Lesson

>> All modern browsers, I mean all including Safari. They have a web assembly, global objects. And this global object is the primary API on how we're going to access web assembly and all of our web assembly methods. They have five static methods. You don't have to instantiate web assembly if the new these are static methods.

They're compile, which compiles wasum and outputs just bytecode compiled streaming which compiles lame from a stream. Which is actually a faster way of loading and instantiating or just loading our wasum file. But what we really care about is instantiate and instantiate streaming. These are the ways of it takes a web assembly module.

It compiles it and then it instantiates versus just compile which it just compiles it. You still need to at that point, instantiate it within the browser. That means load it up and get it loaded into the memory of the browser for the engine to run. So to do this we actually have to use instantiate and instantiate streaming.

All major browsers supports instantiate streaming except for Safari. And Safari is still a widely used browser, so we're gonna have to use instantiate. So we're gonna have to make two Methods for this. And we'll create this utility loader class, which we're going to use for the rest of the class.

And it's just an easy way of wrapping these ways of fetching and compiling web assembly. But we're gonna make the utility class and it just obfuscate the rest of that away. Wo we don't have to worry about it anymore. So, for my instructions here. Lets create a [INAUDIBLE] node.

And lets create a new directory. Let me say, [INAUDIBLE] JS, we got CD in there. And I'm gonna touch a file called loader JS And go into j s. I try to explain like everything I'm doing most of the time. I use a touch command as a lazy way of creating files.

Touch, it just modifies the timestamp on a file. And if it doesn't exist, it creates the file for you. It's a really quick and dirty way of creating files very quickly. Not related to this course. I think I bring it up in full stack or front end, but yeah, just in case you're wondering, I don't wanna use commands that don't make any sense.

I'm gonna make this a class. You don't have to make this a class, but it's totally semantics up to you. But I like using classes when possible as it just encapsulate this data. So I'm gonna call this wagon loader. And, of course a class has a constructor. And constructor is gonna be empty for now.

It's like to do anything. And let's create a function or a method called Wissam, doesn't do anything yet. And then we're gonna create that Wissam fallback, just for Safari. And if you're asking me do I feel bad about calling on Apple, no. They're like always behind. I don't know why, they're behind on service workers.

They're behind on this. I don't know what's going down in Cupertino. I hope they catch up soon. But I imagine that instantiate streaming will be supported pretty soon in Safari, but until then, we have to make this fallback, okay? So, and I'm just following on here. Our YS a method, the way we're going to load the file is we just give it a path.

And then we're going to fetch. And this question was asked earlier about, well, how do we fetch our web assembly? How do we pull it all together? Where's the JavaScript come in? This is where it comes in. So we're going to use the fetch API, which is for the old school of us, it's the same as ex HR or not same as HR.

But it's just a way of fetching files. And we're going to fetch that. We're going to pass that to our web assembly, instantiate static method, which is going to fetch the file and instantiate it. And then we're going to grab the imports. And then we're going to see how to use those imports in JavaScript.

All right. So, as I said before, rather than discuss, is going to take a path and we'll give this a path too. And the path is just the URL or location of the file we're trying to fetch. So I like to add in, console statements. Just so we know we're doing in case something goes wrong, which it will.

Something always goes wrong. But that's okay. We're engineers we deal with it. So I like to add console statements just to let me know what's happening. So I'm going to say fetching, [INAUDIBLE] This string say fetching, Whereas, yeah. So we're talking about something else just, alerts in the console.

So next let's check to make sure our browser supports streaming. So I would say if not web assembly dot instantiates streaming. So it doesn't support instantiate streaming. Let's just call our fallback. Say wasn't fallback. And then we're gonna pass it the path as well. And it's always good to think of fallbacks.

I know they're not popular but remember back in a day when you go, or this even happens today. Remember back in a day when you go on website and it was like, I'm sorry your browser doesn’t currently support this, please use Chrome or whatever. That's really frustrating. I don't think that's good practice unless you absolutely have to do that, like you're making a cutting edge demo or something like that.

So in general, we try to be good citizens and always create fallbacks wherever possible if it's not too cumbersome. But so we'll jump back to the web and fall back in a second, which is going to look very similar to this, just there's an intermediate step. But for now, let's say, We're gonna pull up instance which is the instance of the modules that we're loading.

And we're gonna say, we're gonna wait. And, oops, let me put a sync, there we go. What's ref a sync, probably it would have yelled at me in a second. And we're gonna await webassembly dot instantiate streaming, thank you. And we're gonna pass it up just a fetch.

So we're going to fetch that path. And fetch, of course, returns a promise, but we're waiting so it's okay. And essentially it's streaming is going to take that promise to execute it. And then take the bytes better returned, compile them down and it's going to return an instance of our x of the web assembly module.

From there, we want to return the instance if it exists. And then return the exports off instance. In this case, the export is just going to be the function that we exported. Remember earlier how I made that mistake, and I forgot to export that function. There's nothing in my web assembly.

Well, now that we did, it's only going to export this one function. So right now it just contains the minus one function that we wrote earlier. And for jumping to the Wiseman fallback, it's gonna copy this because it's a log. So say using fallback. Just to let us know that we are on a different code path now.

So now we have to do things a little bit more manually. So we're gonna say, We're gonna wait the response from the fetch same as before. Except this time we have to create an in between byte array. So the fetcher is going to return the web assembly file, the Wissam file.

And again, the Wissam file is in a binary format, so it's just a stream of bytes. So we need to convert those bytes into an array buffer so we can actually use them. And we'll cover array buffers towards the end of the class. They can be a bit confusing, they can be a bit challenging honestly, like coming from my own perspective, when I first started learning about these things.

Array buffers are a little bit tricky to reason about. So I'm gonna leave those to the end of the class and we can dive a bit more into them. But for now, we know that an array buffer is just an array of raw binary data. So we're gonna say a weights, response, there is a response.

I'm gonna say array. And we're gonna convert it to an array buffer. All right, so now we can take these bytes and then we can pass those to web assembly associates. So same as before, We're grabbing that instance. And we're gonna say web assembly dot instantiate. And we're going to just instantiate it with these bytes, rather thanks just the path.

And then like as before, we're going to return, .All right, everybody, with me so far? Thumbs, hands. Two thumbs. All right, yeah, this seems like a bit of work upfront. But this will save us time later down the line because we're just gonna reuse these utility paths. We can't just fetch in binary data.

And that's what Jasmine is just binary data, because JavaScript would know what to do with it. It's a stream of ones and zeros and machine code. It doesn't mean anything. So we have to use a web assembly API. First, to convert into a useful format so that the JavaScript engine understands that.

And then we start playing with web assembly.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now