Young girl walking over railway track by Johannes Plenio

Introducción a AssemblyScript: cómo hacer WebAssembly más fácil para programadores de JavaScript

Gonzalo Ruiz de Villa
Sep 5 · 6 min read

tl;dr Introducción a AssemblyScript: explico qué es WebAssembly, por qué AssemblyScript es una alternativa de construcción de WebAssembly interesante para programadores de JavaScript y comento un sencillo proyecto de manipulación de imágenes que permite comparar las implementaciones de JavaScript y AssemblyScript.

WebAssembly es una de las grandes revoluciones que llegan a la web, aunque no es Web ni es Assembly. WebAssembly, también conocido como Wasm, es un bytecode eficiente, seguro y de bajo nivel para la Web.

Es decir, por un lado no es un lenguaje ensamblador sino bytecode. Aunque ambos son similares en el sentido de que aunque no son lenguajes de alto nivel, se pueden entender razonablemente, cosa que no pasa con el código máquina. Esto los coloca en una categoría de lenguajes intermedios entre los lenguajes de alto nivel y el código máquina. La principal diferencia entre el lenguaje ensamblador y el bytecode es que el primero se crea para las CPUs y el segundo para máquinas virtuales, es decir, uno para hardware y otro para software.

Por cierto, existe una versión textual del bytecode llamada WebAssembly Text Format o Wat para abreviar.

Y además, aunque se dice que es para la Web, no es sólo para la Web ya que se puede usar para aplicaciones de escritorio, serverless o, incluso, para Crypto y Smart contracts.

Efficiente

WebAssembly fue diseñado para tener un formato de fichero binario muy compacto, rápido de descargar y de compilar a código máquina. Tanto es así que, además, permite incluso compilar el código a la vez que se está descargando. Esta característica se llama Streaming Compilation.

Usar un módulo de Wasm desde JavaScript es tan sencillo como:

La siguiente forma de cargar módulos Wasm propuesta por Das Surma (https://dassur.ma/things/raw-wasm/) te permitirá usar de forma robusta el Streaming Compilation. Funcionando aunque el `Content-Type` no esté correctamente establecido a application/wasm (que hace que falle en Firefox, por ejemplo) o si usas Safari (que todavía no soporta instantiateStreaming)

Seguro

Se ha trabajado mucho en la Web para proporcionar un entorno seguro que nos proteja de intenciones maliciosas, y Wasm continúa en la misma línea. Por ejemplo, al igual que JavaScript, Wasm se ejecuta en un entorno Sandbox que lo aísla del entorno de producción. Como consecuencia de esto, para acceder al file system se tiene usar la Web File Api, al igual que se haría usando JavaScript.

Bytecode

Los principales objetivos en el diseño de Wasm fueron que pudiera ser codificado en un formato binario muy eficiente desde el punto de vista del tamaño y del tiempo de carga a la par que pudiese ejecutarse a velocidades nativas y pudiese, además, aprovecharse de las capacidades de hardware comunes de un amplio espectro de plataformas.

Estos objetivos fueron los que obligaron a construir algo nuevo (usando asm.js como punto de partida) en lugar de usar LLVM, el bytecode de Java o .Net. Por todo ello, se diseñó un nuevo formato de instrucciones binario que es un objetivo de compilación para lenguajes de alto nivel como C, C++ o Rust.

`Wat` should I do if I want to program WebAssembly?

El saber no ocupa lugar, así que si te apetece aprender Wat ¡adelante!, aunque inspeccionando el siguiente código, probablemente si dominas JavaScript te gustaría alguna alternativa más sencilla:

(;
Filename: add.wat
This is a block comment.
;)
(module
(func $add (param $p1 i32) (param $p2 i32) (result i32)
local.get $p1 ;; Push parameter $p1 onto the stack
local.get $p2 ;; Push parameter $p2 onto the stack
i32.add ;; Pop two values off the stack and push their sum
;; The top of the stack is the return value
)
(export "add" (func $add))
)

Si lo tuyo es JavaScript, entonces alternativas como C, C++, Rust y lenguajes similares probablemente tampoco te resultarán atractivas, aunque probablemente será cuestión de tiempo que esa situación cambie. Afortunadamente, mientras tanto, existe una alternativa que probablemente sí te encajará: AssemblyScript

AssemblyScript

AssemblyScript (AS) es un subconjunto de TypeScript que es a su vez JavaScript con tipos. Este subconjunto de TypeScript se puede compilar a Wasm fácilmente, con lo que podemos aprovechar los conocimientos de JavaScript para desarrollar Wasm.

Para ilustrar cuánto se parecen JavaScript y AssemblyScript, he preparado este pequeño proyecto en el que manipulo una imagen tanto con JavaScript como con AssemblyScript compilado a Wasm. Puedes encontrarlo aquí: https://github.com/gonzaloruizdevilla/image-manipulation-assemblyscript

En el proyecto se muestra una imagen que se carga dentro de un canvas y varios botones que aplicarán distintos filtros a la imagen. Los botones ejecutarán el filtro con JavaScript o con Wasm generado con AssemblyScript:

Application preview

Aplicando los filtros obtendremos imágenes como estas:

Inverted image
Grayscale
Emboss

Para usar el proyecto, tras clonarlo de Github, puedes instalar la dependencia de AssemblyScript y compilar el fichero de AssemblyScript index.ts con las siguientes instrucciones:

Es interesante hacer notar que cuando se invocan funciones de Wasm desde JavaScript, los argumentos de la llamada solo pueden ser de los siguientes tipos:

  • i32: 32-bit integer
  • i64: 64-bit integer
  • f32: 32-bit float
  • f64: 64-bit float

Evidentemente, no podemos pasar la imagen a través de un argumento de la llamada a Wasm. Por lo tanto, para poder enviar la información de la imagen a Wasm, primero hay que dejarla en una zona compartida de memoria entre el contexto de JavaScript y Wasm que se crea instanciando la clase WebAssembly.Memory. Después dicha instancia se usa al instanciar el módulo Wasm, como puedes ver a continuación:

Reservando memoria para Wasm

Antes de invocar a Wasm, copiamos los datos de la imagen del canvas en la memoria compartida. Después invocamos al filtro de Wasm, leemos la respuesta y la guardamos en imageData y, por último, enviamos imageData al contexto del canvas para que la imagen se pinte.

En el proyecto , hay cuatro funciones de manipulación tanto en JavaScript como en AssemblyScript: invert, grayscale, sepia y convolve (esta última para aplicar los filtros de blur, edge detection y emboss). Como podemos ver son muy similares:

JavaScript version
AssemblyScript version

Como podéis ver, el código es extremadamente parecido, pero con tipos y trabajando a un nivel un poco más bajo, que es lo que nos permite usar todo el potencial de Wasm. Así que, ¡ahora solo toca animarse, empezar a jugar con AssemblyScript y coger confianza en la tecnología Wasm, que va a ser una parte cada vez más importante de la web en los próximos años!

Referencias

WebAssembly
https://webassembly.org/

WebAssembly: Neither Web, Nor Assembly, but Revolutionary https://www.javascriptjanuary.com/blog/webassembly-neither-web-nor-assembly-but-revolutionary

Raw WebAssembly
https://dassur.ma/things/raw-wasm/

Understanding Text Format
https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format

Writing WebAssembly by Hand https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html

WebAssembly Text Format https://webassembly.github.io/spec/core/text/index.html

Making WebAssembly even faster: Firefox’s new streaming and tiering compiler https://hacks.mozilla.org/2018/01/making-webassembly-even-faster-firefoxs-new-streaming-and-tiering-compiler/

WebAssembly, bytecode for browser https://www.scriptol.com/programming/wasm.php

asm.js Spec Working Draft http://asmjs.org/spec/latest/

WebAssembly.Memory() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory

Pixel manipulation in canvas http://www.phpied.com/pixel-manipulation-in-canvas/

Canvas pixels #2: convolution matrix https://www.phpied.com/canvas-pixels-2-convolution-matrix/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade