17 puntos por GN⁺ 2025-09-18 | 2 comentarios | Compartir por WhatsApp
  • El estándar Wasm 3.0 fue anunciado oficialmente e incluye funciones de gran escala preparadas durante 6 a 8 años
  • Con espacio de direcciones de 64 bits, recolección de basura, referencias tipadas, tail calls y manejo de excepciones, ahora es más fácil compilar lenguajes de alto nivel a Wasm
  • Las principales novedades ayudan a crear aplicaciones de alto rendimiento, runtimes para múltiples lenguajes, mayor seguridad y escalabilidad
  • También es adecuado para casos fuera del entorno web, donde se necesita manejar mayores volúmenes y conjuntos de datos más grandes
  • Ya cuenta con soporte en los principales navegadores web y pronto estará completo también en motores independientes como Wasmtime, consolidando aún más a Wasm como una plataforma de ejecución de propósito general

Resumen del lanzamiento de Wasm 3.0

  • La versión 3.0 del estándar WebAssembly se lanzó el 17 de septiembre de 2025
    • Es la primera gran actualización en 3 años desde la versión 2.0 (finalizada en 2022), que introdujo instrucciones vectoriales, operaciones masivas de memoria, múltiples valores de retorno y tipos de referencia simples
    • Mientras el Community Group y el Working Group del W3C siguieron desarrollándolo, esta versión incorpora grandes funciones preparadas durante 6 a 8 años, por lo que representa un cambio de gran magnitud
    • Wasm mantiene su filosofía como lenguaje de bajo nivel, pero refuerza su sistema de memoria y de tipos para dar mejor soporte a la compilación de lenguajes de alto nivel
  • Las funciones desarrolladas después de la versión 2.0 ya quedaron cerradas y pasan a formar parte del estándar Live, mientras se amplía su soporte en navegadores web y motores independientes

Cambios principales y nuevas funciones

  • Espacio de direcciones de 64 bits
    • Se pueden declarar memorias y tablas con el tipo i64
    • El espacio de direcciones de las aplicaciones Wasm puede expandirse desde unos 4 GB hasta el límite físico (teóricamente 16 exabytes)
    • En la web se aplica un límite de 16 GB, pero en el ecosistema no web resulta útil para soportar aplicaciones y conjuntos de datos a gran escala
  • Múltiples memorias
    • Es posible declarar y acceder directamente a múltiples objetos de memoria dentro de un mismo módulo
    • Puede aprovecharse para fusión de módulos, separación del espacio de direcciones, buffering, seguridad y otros usos
    • Herramientas de enlace estático como wasm-merge pasan a poder usarse con todos los módulos Wasm
  • Recolección de basura (GC)
    • Además de la memoria lineal, se admite almacenamiento administrado automáticamente por el runtime de Wasm
    • Los compiladores declaran directamente layouts de datos como tipos struct/array y enteros unboxed
    • Solo se proporcionan los bloques fundamentales para administración de memoria, mientras que sistemas de objetos de alto nivel o closures pueden diseñarse de forma independiente según el lenguaje de implementación
  • Referencias tipadas
    • El sistema de tipos de Wasm se amplía para describir con mayor precisión la forma de los valores en heap y las referencias a funciones
    • Soporta subtyping y recursión de tipos, y con la nueva instrucción call_ref permite llamadas indirectas seguras a funciones sin verificación de tipos en runtime
  • Tail calls
    • Se admite la estructura de tail call, que retorna directamente sin usar espacio adicional en la pila de la función existente
    • Puede aprovecharse en lenguajes funcionales o en optimizaciones internas de runtimes
  • Manejo de excepciones
    • Introduce un sistema nativo de manejo de excepciones dentro de Wasm
    • Permite declarar etiquetas y payloads de excepción, captura opcional y manejadores de excepciones a nivel de bloque
    • Mejora la portabilidad y el rendimiento sin recurrir a métodos ineficientes que antes se desviaban hacia JS
  • Instrucciones vectoriales relaxed
    • Para responder a diferencias de hardware en instrucciones SIMD, se ofrecen variantes relaxed que dejan ciertos detalles de comportamiento a libertad de la implementación
    • Esto permite diversas optimizaciones dentro del conjunto de comportamientos válidos
  • Perfil determinista
    • Incluso en situaciones donde el resultado de una misma instrucción puede no ser determinista (como operaciones de punto flotante o relaxed SIMD), se define una ejecución determinista entre plataformas
    • Esto permite garantizar reproducibilidad y portabilidad en blockchain, sistemas reproducibles y casos similares
  • Sintaxis de anotaciones personalizadas
    • Se agrega una sintaxis de anotaciones legible y escribible por humanos dentro del código fuente
    • Aunque el estándar no la interpreta directamente, podrá aprovecharse en futuras implementaciones del estándar y sus extensiones

Integración con JavaScript y compatibilidad

  • JS string builtins
    • Los valores de cadena de JS pueden pasarse y manipularse en Wasm como externref
    • Importando nuevas funciones integradas, Wasm puede usar directamente cadenas externas de JS en su interior

Utilidad y perspectivas de Wasm 3.0

  • Proporciona una base esencial para la compilación hacia Wasm de lenguajes de programación avanzados
  • Lenguajes principales como Java, OCaml, Scala, Kotlin, Scheme, y Dart también han comenzado a aprovechar activamente las funciones de GC

Estado de creación de la especificación y despliegue

  • Wasm 3.0 es el primer estándar creado con la nueva cadena de herramientas SpecTec
  • La mayoría de los principales navegadores web ya soportan Wasm 3.0, y motores independientes como Wasmtime también estarán completos pronto
  • El estado de soporte por motor puede consultarse en la página de Wasm feature status

2 comentarios

 
coremaker 2025-09-18

¿No empezarán a surgir también intentos de crear una base de datos en memoria?

 
GN⁺ 2025-09-18
Opiniones en Hacker News
  • La parte que realmente entusiasma es que 64 bits se vuelva el valor predeterminado de la especificación; especialmente las webapps como los editores de video en línea siguen teniendo muchas limitaciones por el límite de 32 bits. En Figma también han vivido estas restricciones de primera mano. Una cosa que me da curiosidad es si en dispositivos móviles se mantendrá el límite de memoria direccionable por pestaña, que normalmente lo define el SO, así que quizá no esté ligado directamente al espacio de 32 bits.

    • Me pregunto si de verdad tiene sentido que una app como un editor de video viva dentro de un navegador de documentos. Da pena que, aunque existen sistemas operativos nativos bien hechos, ya casi nadie los use. Si realmente se necesita una máquina virtual más potente que la virtualización que ya ofrece un proceso tradicional del sistema operativo, me parecería más honesto diseñar una abstracción pensada para ese propósito. Se siente como forzar a un lector de documentos simple a convertirse en editor de video.

    • Por desgracia, la función Memory64 trae una penalización de rendimiento considerable. En el viejo modelo de 32 bits, el runtime asignaba siempre los 4 GB completos, así que prácticamente no hacían falta verificaciones de límites; en 64 bits sí hay que comprobar los límites manualmente. Si de verdad necesitas más de 4 GB de memoria, no queda de otra.

    • También emociona la llegada de GC, tipos de referencia y la API de strings de JS. Qué gusto volver a ver una J; me pregunto cómo estará.

    • Parece hasta natural que una webapp se tope con el límite de 4 GiB de memoria. Vivimos en una época donde hasta para leer el correo parece que 512 GiB fueran el mínimo.

  • Me parece fascinante que vayan a agregar garbage collection. Antes no se podía acceder directamente al stack desde Wasm, así que los enfoques tradicionales de GC como el stack scanning eran imposibles. Gracias a eso se mantiene el carácter de lenguaje de bajo nivel, pero con struct, tipos array, unboxed tagged int y otros mecanismos para describir explícitamente el layout de memoria, mientras Wasm se encarga de la asignación y la vida útil. Hasta ahí llega. Impresionante.

    • También se siente novedoso que, con la llegada del GC, la estructura siga soportando entornos sin GC. En ese sentido se parece a D (D también soporta compilación y ejecución rápidas tanto con GC como sin GC). Por cierto, el compilador LDC de Dlang ya puede generar Wasm: Generating WebAssembly with LDC

    • Me pregunto si este cambio permitirá reducir el tamaño de los objetos WebAssembly.Memory. Es un tema muy importante, porque aunque se libere memoria, esta sigue quedándose asignada dentro del navegador issue 1 issue 2

  • Me pregunto cuándo llegará el momento en que WASM pueda tocar el DOM directamente. Siento que ese era el propósito central de WASM, pero ahora se siente como un monstruo aparte, casi sin relación con la web. También me pregunto cuándo dejará de ser necesario usar JavaScript.

    • Ojalá esta parte y el acceso a multithreading queden bien soportados. Me gustaría usar una app en Rust, compilarla a wasm y cargarla directamente así:

      
      

      En cosas como webapps de alto rendimiento o extensiones de navegador, los problemas de memoria y rendimiento sí son muy reales, así que esto ayudaría muchísimo. Si la app está basada en wasm, incluso podrías saltarte v8 y usar directamente motores como wasmer. Creo que las tecnologías web terminan en apps de escritorio tipo Electron porque las APIs de escritorio son demasiado malas y poco portables. Si mejora el soporte nativo de WASM, apps como Slack, VSCode o Discord podrían volverse más ligeras.

    • Incluso ahora se puede acceder al DOM desde programas WASM. Solo que hay que pasar por las APIs existentes de JS. En algún momento se discutió una API exclusiva para WASM, pero terminó descartándose porque traía demasiadas desventajas.

    • Estoy esperando y observando, con la esperanza de ver un lenguaje frontend bien diseñado. Pero me pregunto si de verdad es tan ineficiente pasar por wrappers de JS para acceder al DOM. La mayor parte del código ya es ineficiente de por sí, así que no creo que el overhead de eso destaque tanto en la práctica.

    • Si crees que JavaScript tiene problemas, cuando veas el lado del DOM te va a parecer peor.

    • Tener referencias al DOM es complicado porque implicaría poder observar directamente objetos sujetos a garbage collection. Bajo el modelo de seguridad de JavaScript en la web, no debería poder inspeccionarse el interior del GC. Si WASM tuviera punteros al DOM, el problema sería cómo manejar eso. Tal vez pueda volver a discutirse cuando el GC esté plenamente incorporado, pero en un WASM sin GC parece un problema casi sin solución.

  • Dejé de seguir el desarrollo de WASM durante más o menos un año y apenas ahora me entero de que pasaron a un modelo de releases por versión. Yo pensaba que varias funciones seguirían siendo opcionales, pero ahora parece que para poder decir que algo es compatible con cierta versión (WASM 3.0, etc.), cada implementación tiene que soportar todas las funciones. Me pregunto cuál será el segundo runtime fuera del navegador en dar soporte completo a 3.0; apostaría por wasmtime como el primero (excluyendo deno, porque está basado en v8). GC en particular me parece una función bastante complicada. También me pregunto si alguien sabe cómo se conecta el release 3.0 con el viejo modelo "evergreen": uno donde se siguen actualizando borradores del estándar sin definir una versión final oficial aparte. El Candidate Recommendation Draft más reciente se considera de hecho el estándar actual estado de features de wasm noticias de wasm 2.0 borrador más reciente del estándar

    • wasmtime ya soporta todas las funciones principales de wasm 3.0. GC lo implementó mi colega Nick Fitzgerald hace unos años, y el tail call lo implementaron el año pasado Jamey Sharp y Trevor Elliott con soporte completo (sin restricciones de firma y sin necesidad de trampolines). El manejo de excepciones también ya está listo y pronto saldrá formalmente. Este release de "3.0" puede verse como una señal de que cada motor ya venía teniendo listas estas funciones. Soy maintainer de wasmtime y Cranelift.

    • Wizard es una herramienta de investigación, pero soporta todo Wasm 3.0. Eso sí, solo tiene intérprete y compilador baseline; no cuenta con un compilador optimizado como v8 o wasmtime. Por eso su velocidad es baja.

    • Parece que el versionado terminará funcionando como el enfoque de feature sets de JavaScript, o sea, en términos de qué conjunto de funciones soporta cada runtime. Me da curiosidad cómo funciona el feature discovery en wasm.

  • Da muchísimo gusto ver que se agregó soporte de GC. Antes, como no había acceso directo al stack en WASM, implementar GC tradicional basado en stack scanning era prácticamente imposible.

  • Siento que la comunidad de WebAssembly debería preocuparse más por la experiencia de desarrollador (DX). Yo mismo escribí un compilador apuntando a Wasm y fue bastante incómodo. Pensaba que era un lenguaje con semántica bien formalizada, pero al generar Wasm con Binaryen.js nunca sentí realmente que estuviera apuntando a un conjunto de instrucciones claro. Creo que en parte es culpa de Binaryen y de la falta de documentación. Al menos escribir snippets de texto de Wasm sí era divertido compilador wasm jasmine

    • Binaryen arrastra mucho legado de cuando Wasm era un AST. Las funciones nuevas son difíciles de encajar en ese modelo antiguo. En nuestro compilador definimos aparte una estructura de datos para una representación abstracta de Wasm, y por defecto exportamos .wasm; en debug, .wat. Me parece bastante intuitivo, así que creo que el instruction set está bien backend wasm de Scala.js

    • Probé Binaryen desde TypeScript y sentí una frustración parecida. Me cambié a wasm-tools, basado en Rust, y la experiencia fue mucho mejor.

    • Me da curiosidad qué parte en concreto te resultó difícil. A veces los validation errors son realmente desesperantes, así que en Wizard pusimos una opción --trace-validation, que visualiza el proceso de validación de forma más clara.

    • La documentación y los bindings de binaryen.js sí se sienten bastante insuficientes. Ahorita el enfoque está puesto en mejorar las optimizaciones del Binaryen core, así que la parte de JS/TS avanza más lento. Aun así, si alguien dedicara tiempo a mejorar los bindings para JS/TS, creo que sería bueno para todos.

    • También me quedó la sensación de que sería más fácil escribir código assembly puro desde cero. La mayoría de los materiales se concentran en herramientas de Rust, pero la experiencia de escribirlo a mano también importa. Un compiler y el assembly son cosas distintas. Hace falta una visión donde no solo a los desarrolladores de compiladores les interese Wasm.

  • Sigo teniendo expectativas con WASM; este release se ve muy bien. Estoy corriendo plugins de WASM con mucho tráfico en envoy, y también uso WASM para plugins de apps de terminal como zellij. En proyectos pequeños incluso mantengo una webapp en wasm basada en rust leptos. Si soy sincero, quizá 2 de esos 3 casos no sean la elección técnicamente óptima, pero siento que esta tendencia va a seguir avanzando bien. Gracias a todos por el esfuerzo.

  • Lo simple es mejor. Lo que yo quiero es una forma más fácil y rápida de pasar struct de Go. Ojalá meter o sacar un struct de Go del runtime no enrede todo el código ni me obligue a usar soluciones pegadas con cinta. También me serviría una solución genérica que funcione para varios lenguajes, aunque tenga limitaciones realistas. Para mí, Go es lo más importante.

    • Totalmente de acuerdo. Y en lenguajes sin GC, en la práctica tampoco es mucho mejor. De hecho, los runtimes con GC en wasm suelen ser aún más desastrosos. La peor experiencia que he tenido en JavaScript hasta ahora ha sido limpiar punteros a mano. En C++, al salir del scope el destructor se encarga; en wasm y js hay que manejarlo todo manualmente, y hasta mis recuerdos con JNI me parecen mejores (incluyendo Go). Y cuando por fin logras pasar un struct, el overhead por llamada es tan alto que terminas envolviendo todo en bloques más grandes. Yo también solo quiero que al menos el pipeline de wasm mejore, porque hasta ahora ha sido duro.

    • En código nativo la solución es la misma: ajustarse entre lenguajes a una estructura estándar (como un struct de C) o serializar/deserializar. Cuando mezclas varios runtimes y los lenguajes no lo soportan directamente, de verdad se vuelve una pesadilla. Es bastante obvio por qué eso es un problema.

    • No sé exactamente qué es lo que quieres, pero el component model, que es la base de WASI, probablemente ayude. Ese modelo permite que cada módulo defina cómo mapea los datos en memoria (más adelante incluso en el heap con GC), y también deja definir tipos como struct en la interfaz para que el compilador genere automáticamente el glue code.

    • Esto me suena más a algo del terreno de librerías que de la especificación de WASM. Internamente sí he tenido buenas experiencias usando generadores de código para este tipo de cosas.

  • Estoy esperando soporte para OpenMP. Estoy corriendo experimentalmente un build web de Solvespace, y si OpenMP funciona sería una mejora enorme demo en línea de solvespace, es un CAD de código abierto que corre en el navegador.

    • Solvespace me parece una herramienta increíble. Hace tiempo diseñé una carcasa de teclado dividido siguiendo tutoriales de YouTube y luego la fabriqué en CNC. Permitía obtener resultados muy rápido. Gracias por mantenerlo.

    • Creo que es la mejor UI web basada en WASM que he visto hasta ahora. Me da curiosidad cuál fue la parte más difícil al llevar el build de escritorio a Emscripten.

  • Dejo esto porque todavía no lo vi mencionado: me pregunto si la función multiple-memories podría usarse para evitar copias duplicadas al mapear recursos de WebGPU. Ahora mismo, como el mapeo vive en un ArrayBuffer, desde WASM hay que copiar pasando por JS y el rendimiento sale perdiendo. Sospecho que varias memorias WASM junto con la función de address spaces de Clang/LLVM podrían ser la solución, aunque no sé si en la práctica sea tan simple.

    • Existe esta discusión sobre soporte de toolchain para multi-memory, pero no sé si de verdad llegó a implementarse en LLVM algo que aproveche varios espacios de direcciones.

    • Todo esto me recuerda a la vieja memoria segmentada y a los far pointers. Últimamente he estado programando juegos para Game Boy, así que mapear memoria tiene su parte "divertida", pero no me gustaría repetir eso en un entorno sin esas limitaciones. Si en la era de DOS/Win16 enterraron los far pointers, fue por buenas razones.