Cristhian Villegas
Frontend15 min read1 views

WebAssembly Garbage Collection (WasmGC): Soporte Completo en Navegadores en 2026

WebAssembly Garbage Collection (WasmGC): Soporte Completo en Navegadores en 2026

¿Qué es WebAssembly Garbage Collection (WasmGC)?

WebAssembly (Wasm) fue diseñado originalmente como un objetivo de compilación para lenguajes como C, C++ y Rust — lenguajes que gestionan la memoria de forma manual. Pero, ¿qué sucede con lenguajes que tienen recolección de basura automática, como Java, Kotlin, Dart o Go? Antes de WasmGC, estos lenguajes tenían que incluir su propio recolector de basura completo como parte del binario Wasm compilado, lo que resultaba en archivos enormes, mala integración con las herramientas de desarrollo del navegador y trabajo duplicado que la VM del navegador ya realiza de forma nativa.

La propuesta WasmGC (formalmente parte de Wasm 3.0, estandarizada el 17 de septiembre de 2025) introduce tipos con recolección de basura de primera clase — struct y array — directamente en el sistema de tipos de WebAssembly. En lugar de que los lenguajes con GC compilen su propio asignador de memoria y recolector en memoria lineal, ahora delegan la asignación y recolección de objetos al recolector de basura integrado de la VM del navegador (V8, SpiderMonkey o JavaScriptCore).

Concepto clave: WasmGC no añade un nuevo recolector de basura — permite que los módulos Wasm usen el mismo GC que ya impulsa JavaScript en cada navegador.

Antes de WasmGC: el enfoque de memoria lineal

Antes de WasmGC, compilar un lenguaje con GC a Wasm se veía así:

  • El runtime del lenguaje (incluyendo su recolector de basura) se compilaba a Wasm y se enviaba como parte del binario
  • Todos los objetos vivían en la memoria lineal de Wasm — un arreglo plano de bytes gestionado manualmente
  • El GC embebido tenía que recorrer la memoria lineal para encontrar objetos vivos, sin ayuda de la VM del navegador
  • Interactuar con objetos JavaScript requería "código puente" complejo y costoso
  • Las DevTools del navegador no podían inspeccionar objetos gestionados por el GC dentro de la memoria lineal

Después de WasmGC: integración nativa con la VM

Con WasmGC, el panorama cambia drásticamente:

  • Los lenguajes definen tipos struct y array en la sección de tipos del módulo Wasm
  • La asignación de objetos usa instrucciones struct.new y array.new
  • El GC del navegador rastrea y recolecta estos objetos automáticamente — no se necesita un GC embebido
  • Los objetos GC pueden referenciar objetos JavaScript sin fricción y viceversa
  • Las DevTools pueden inspeccionar objetos WasmGC de forma nativa

Soporte en navegadores en 2026: cobertura completa

A abril de 2026, WasmGC ha alcanzado el estado Baseline Newly Available (desde el 11 de diciembre de 2024), lo que significa que todos los motores principales de navegadores lo soportan. La cobertura global es de aproximadamente 87.9% de los usuarios según caniuse.com.

Navegador Primera versión con WasmGC Fecha de lanzamiento Motor
Chrome 119 Octubre 2023 V8
Edge 119 Octubre 2023 V8 (Chromium)
Firefox 120 Noviembre 2023 SpiderMonkey
Opera 105 Finales de 2023 V8 (Chromium)
Safari (macOS e iOS) 18.2 Diciembre 2024 JavaScriptCore
Samsung Internet 25 2024 V8 (Chromium)
Opera Mobile 80 2025 V8 (Chromium)
Safari fue el último en sumarse. Safari 18.2 (diciembre 2024) finalmente activó WasmGC por defecto, completando la cobertura en todos los navegadores principales. En iOS, todos los navegadores usan WebKit internamente, por lo que el soporte de WasmGC en iPhone/iPad depende de iOS 18.2+.

Detección de soporte: verificar WasmGC en tiempo de ejecución

Antes de depender de WasmGC, debes verificar que el navegador del usuario lo soporte. El método más confiable es intentar compilar un módulo Wasm mínimo que use tipos GC:

javascript
1/**
2 * Detectar soporte de WasmGC intentando compilar un módulo
3 * mínimo que declara un tipo struct GC.
4 *
5 * El binario define:
6 *   (module
7 *     (type (struct (field i32)))
8 *   )
9 */
10async function soportaWasmGC() {
11  try {
12    const bytes = new Uint8Array([
13      0x00, 0x61, 0x73, 0x6d, // magic: \0asm
14      0x01, 0x00, 0x00, 0x00, // version: 1
15      0x01,                   // ID sección de tipos
16      0x07,                   // Tamaño de sección: 7 bytes
17      0x01,                   // 1 tipo
18      0x5f,                   // constructor tipo struct
19      0x01,                   // 1 campo
20      0x00,                   // mutabilidad: inmutable
21      0x7f,                   // tipo campo: i32
22    ]);
23    await WebAssembly.compile(new WebAssembly.Module(bytes));
24    return true;
25  } catch {
26    return false;
27  }
28}
29
30// Uso
31const tieneGC = await soportaWasmGC();
32if (tieneGC) {
33  console.log('¡WasmGC soportado! Cargando módulo optimizado...');
34  // Cargar módulo compilado con WasmGC
35} else {
36  console.log('WasmGC no soportado. Usando fallback JS o Wasm lineal...');
37  // Cargar alternativa
38}
Importante: No dependas únicamente del user-agent. La detección por compilación de prueba es el único método confiable, especialmente porque los navegadores basados en Chromium pueden tener diferentes flags de funcionalidades activadas.

Lenguajes que se benefician de WasmGC

WasmGC desbloquea la web como un objetivo de primera clase para lenguajes con recolección de basura. Este es el estado actual de cada ecosistema principal:

Kotlin/Wasm — Beta (estable esperado para finales de 2026)

Kotlin/Wasm es posiblemente el objetivo WasmGC más maduro. Graduó de Alpha a Beta en septiembre de 2025, y Compose Multiplatform para Web alcanzó Beta al mismo tiempo. JetBrains ha sido una fuerza impulsora detrás de la adopción de WasmGC.

kotlin
1// saludo.kt — Ejemplo simple de Kotlin/Wasm
2// Target de compilación: wasmJs (usa WasmGC internamente)
3
4fun saludar(nombre: String): String {
5    val saludo = buildString {
6        append("¡Hola, ")
7        append(nombre)
8        append("! Esto se ejecuta en WasmGC ")
9        append("con recolección de basura nativa del navegador.")
10    }
11    return saludo
12}
13
14// Las data classes se mapean a tipos struct de WasmGC
15data class Usuario(val nombre: String, val puntuacion: Int)
16
17fun procesarUsuarios(usuarios: List<Usuario>): List<Usuario> {
18    // Colecciones, lambdas y data classes funcionan normalmente
19    // Los objetos se asignan como structs WasmGC, no en memoria lineal
20    return usuarios
21        .filter { it.puntuacion > 50 }
22        .sortedByDescending { it.puntuacion }
23}

Para configurar un proyecto Kotlin/Wasm con Gradle:

kotlin
1// build.gradle.kts
2plugins {
3    kotlin("multiplatform") version "2.1.20"
4}
5
6kotlin {
7    wasmJs {
8        browser {
9            commonWebpackConfig {
10                outputFileName = "app.wasm.js"
11            }
12        }
13        binaries.executable()
14    }
15
16    sourceSets {
17        val wasmJsMain by getting {
18            dependencies {
19                implementation("org.jetbrains.kotlinx:kotlinx-browser:0.3")
20            }
21        }
22    }
23}
24
25// Comando de construcción:
26// ./gradlew wasmJsBrowserProductionWebpack

Dart / Flutter Web — soporte estable de WasmGC

Flutter lanzó soporte estable de WebAssembly en Flutter 3.38 (noviembre 2025), con resultados impresionantes: aproximadamente 40% más rápido en carga inicial y 30% menos uso de memoria comparado con la compilación a JavaScript.

bash
1# Crear un nuevo proyecto Flutter para web con Wasm
2flutter create mi_app_wasm
3cd mi_app_wasm
4
5# Compilar para web usando WebAssembly (WasmGC)
6flutter build web --wasm
7
8# La salida en build/web/ contendrá:
9#   main.dart.wasm    — Código Dart compilado con WasmGC
10#   main.dart.mjs     — Bootstrap/código puente JS
11#   index.html         — Punto de entrada con lógica de fallback
12
13# Para desarrollo con hot reload:
14flutter run -d chrome --wasm
Problema conocido (abril 2026): El renderizador Wasm de Flutter (skwasm) tiene problemas de compatibilidad con Firefox y Safari debido a bugs específicos de esos navegadores. Chrome/Chromium es el objetivo más confiable. Flutter automáticamente hace fallback al renderizador CanvasKit (JS) en navegadores no soportados. Sigue el problema de Safari en WebKit Bug 267291.

Java — Backend WebAssembly de GraalVM

Oracle GraalVM para Java 25 introdujo un backend WebAssembly que compila bytecode Java a módulos WasmGC. Este es un logro histórico — Java ahora puede ejecutarse nativamente en navegadores sin applets, plugins ni la incrustación pesada del runtime.

Google ha sido pionero aquí: Google Sheets usa J2Wasm (una herramienta interna) para compilar su motor de cálculo basado en Java a WasmGC, logrando un rendimiento 2x más rápido que la implementación equivalente en JavaScript.

bash
1# Compilar Java a WasmGC usando GraalVM (JDK 25+)
2# Requiere Oracle GraalVM con el componente wasm
3
4# Instalar el componente Wasm
5gu install wasm
6
7# Compilar una aplicación Java a WasmGC
8native-image --target=wasm32-wasi \
9  -o app.wasm \
10  -H:+WasmGC \
11  com.example.Main
12
13# El app.wasm resultante usa tipos struct/array de WasmGC
14# y delega la gestión de memoria al GC del navegador

C# / .NET / Blazor — NO adoptará WasmGC

En una decisión sorprendente pero técnicamente bien fundamentada, Microsoft ha declarado que .NET no adoptará WasmGC v1. Las incompatibilidades fundamentales incluyen:

  • WasmGC v1 no puede soportar punteros interiores, ref ni Span<T>
  • No hay finalización, resurrección, referencias débiles ni handles dependientes
  • No hay soporte para GC concurrente
  • El código de interoperabilidad C/C++ no puede manipular objetos WasmGC fuera de la memoria lineal

Blazor WebAssembly continúa incluyendo el runtime completo de .NET (con su propio GC) compilado a Wasm con memoria lineal. Microsoft dice que "continuará monitoreando la evolución de la especificación post-v1 de WasmGC."

Go — Sin planes activos

A pesar del interés de la comunidad (94+ votos en el issue #63904 de GitHub), el equipo de Go ha etiquetado el soporte de WasmGC como "Sin planificar". Go actualmente compila a Wasm usando memoria lineal con un GC incluido, resultando en binarios grandes (~10-15MB mínimo). Esta sigue siendo un área de frustración para la comunidad.

Otros lenguajes

Lenguaje Estado WasmGC Notas
OCaml Desarrollo activo Compilador wasocaml dirigido a WasmGC
Scheme Prototipo funcional Compilador Hoot (Spritely/Guile)
Scala Experimental Vía puente Scala.js → Wasm o compilación directa

Beneficios técnicos: ¿por qué importa WasmGC?

1. Binarios dramáticamente más pequeños

Al delegar la recolección de basura al navegador, los módulos WasmGC no necesitan incluir una implementación de GC. La diferencia es notable:

Benchmark Binario WasmGC (Java) Binario memoria lineal (C/Rust) Reducción
Fannkuch 2.3 KB 6.1 – 9.6 KB ~62-76%

Para aplicaciones reales, los ahorros son aún más pronunciados porque se elimina no solo el GC sino también el asignador de memoria (implementaciones de malloc/free) y todo el código de contabilidad.

2. Mejor rendimiento

Los objetos WasmGC tienen tipos y estructuras fijos y conocidos en tiempo de compilación. Esto significa que el compilador JIT del navegador puede generar código máquina más eficiente:

  • Sin riesgo de desoptimización — a diferencia de los objetos dinámicos de JavaScript, los accesos a campos de struct WasmGC son siempre type-safe
  • Sin overhead de shadow stack — las implementaciones de GC en memoria lineal requieren un shadow stack para recorrer la pila de llamadas durante el escaneo de raíces; WasmGC elimina esto por completo
  • Inlining especulativo de V8 — entregó aproximadamente un 30% de mejora en la carga de trabajo WasmGC de Google Sheets
  • Optimización con Binaryen — aplicar wasm-opt a módulos WasmGC produce un promedio de 1.9x de mejora en velocidad

3. Interoperabilidad perfecta con JavaScript

Los objetos WasmGC viven en el mismo heap que los objetos JavaScript. El GC del navegador puede rastrear referencias entre ellos, eliminando la necesidad de código puente complejo:

javascript
1// Interoperabilidad JavaScript con un módulo WasmGC
2const instance = await WebAssembly.instantiateStreaming(
3  fetch('app.wasm'),
4  {
5    imports: {
6      // Las funciones JS pueden recibir referencias WasmGC directamente
7      registrarUsuario(refUsuario) {
8        // La VM maneja la referencia — sin serialización necesaria
9        console.log('Procesando usuario:', refUsuario);
10      }
11    }
12  }
13);
14
15// Las funciones exportadas con WasmGC devuelven referencias GC
16const resultado = instance.exports.crearUsuario('Alicia', 100);
17// 'resultado' es una referencia struct WasmGC — el GC del navegador la rastrea

4. Mejor integración con DevTools

Dado que los objetos WasmGC son ciudadanos de primera clase del GC del navegador, las herramientas de desarrollo pueden:

  • Inspeccionar campos y tipos de objetos WasmGC en la pestaña de Memoria
  • Rastrear asignaciones y recolecciones del GC
  • Perfilar el uso de memoria con precisión
  • Detectar fugas de memoria que involucren objetos WasmGC

Impacto real: Flutter Web y Kotlin Multiplatform

Flutter Web con WasmGC

La adopción de WasmGC por parte de Flutter representa uno de los despliegues más grandes de esta tecnología en el mundo real:

  • ~40% más rápido en carga inicial comparado con la compilación a JavaScript
  • ~30% menos uso de memoria en tiempo de ejecución
  • Flutter 3.38 (noviembre 2025) marcó el soporte estable de Wasm
  • Flutter 3.35 comenzó a preparar a los desarrolladores para Wasm como el objetivo de compilación predeterminado
dart
1// Flutter Web con WasmGC — ¡sin cambios de código necesarios!
2// El mismo código Dart compila tanto a JS como a WasmGC
3
4import 'package:flutter/material.dart';
5
6void main() {
7  runApp(const MiApp());
8}
9
10class MiApp extends StatelessWidget {
11  const MiApp({super.key});
12
13  @override
14  Widget build(BuildContext context) {
15    return MaterialApp(
16      title: 'Demo Flutter WasmGC',
17      home: Scaffold(
18        appBar: AppBar(title: const Text('¡Ejecutándose en WasmGC!')),
19        body: const Center(
20          child: Text(
21            'Este árbol de widgets es gestionado por el GC del navegador',
22            style: TextStyle(fontSize: 24),
23          ),
24        ),
25      ),
26    );
27  }
28}

Kotlin Multiplatform para Web

Compose Multiplatform para Web (Beta, septiembre 2025) permite a los desarrolladores compartir código UI entre Android, iOS, Desktop y Web — con el objetivo web compilado a WasmGC:

kotlin
1// Compose Multiplatform — mismo código, múltiples targets incluyendo WasmGC
2@Composable
3fun App() {
4    var contador by remember { mutableStateOf(0) }
5
6    MaterialTheme {
7        Column(
8            modifier = Modifier.fillMaxSize(),
9            horizontalAlignment = Alignment.CenterHorizontally,
10            verticalArrangement = Arrangement.Center
11        ) {
12            Text("Contador: $contador", style = MaterialTheme.typography.headlineMedium)
13            Button(onClick = { contador++ }) {
14                Text("Incrementar")
15            }
16        }
17    }
18}
19
20// Cuando se compila al target wasmJs, toda esta UI
21// se ejecuta como código WasmGC en el navegador

Google Sheets: la prueba a gran escala

Quizás la validación más convincente de WasmGC es la migración de Google del motor de cálculo de Sheets de JavaScript a WasmGC (compilado desde Java vía J2Wasm):

  • Resultado inicial: WasmGC sin optimizar era 2x más lento que JavaScript
  • Después de optimizaciones de V8 y Binaryen: WasmGC se volvió 2x más rápido que JavaScript
  • Eso es una mejora de 4x desde la compilación inicial sin optimizar hasta la versión final optimizada
  • Demuestra que WasmGC está listo para producción a escala de Google

WasmGC post-MVP: ¿qué viene después?

WasmGC tal como se incluyó en Wasm 3.0 es el "MVP" (Producto Mínimo Viable). Varias propuestas están en progreso para extender sus capacidades:

Propuesta Fase Qué añade
JS Promise Integration Fase 4 (Estandarizar) async/await transparente entre JS y Wasm — sin wrappers de callbacks
Stack Switching Fase 3 (Implementación) Habilita corutinas, green threads y async eficiente en Wasm
JS String Builtins Incluido (Wasm 3.0) Operaciones nativas de strings sin código puente JS — ya disponible
Shared-Everything Threads Fase 1 Compartir objetos GC entre hilos — crítico para compatibilidad con .NET
More Array Constructors Fase 1 Formas adicionales de crear y manipular arrays WasmGC
JS Promise Integration es particularmente emocionante — en Fase 4, está casi estandarizado y permitirá que los módulos WasmGC hagan await directamente de Promises de JavaScript sin el complejo código de trampolín que se requiere actualmente.

Cómo optimizar módulos WasmGC con Binaryen

Binaryen es el kit de herramientas esencial de optimización para WebAssembly. Su herramienta wasm-opt puede mejorar significativamente el rendimiento de los módulos WasmGC:

bash
1# Instalar Binaryen
2npm install -g binaryen
3
4# Optimizar un módulo WasmGC (optimización agresiva)
5wasm-opt -O3 --enable-gc --enable-reference-types \
6  input.wasm -o optimizado.wasm
7
8# Con pases adicionales específicos para WasmGC
9wasm-opt -O3 \
10  --enable-gc \
11  --enable-reference-types \
12  --enable-strings \
13  --type-merging \
14  --type-ssa \
15  --global-refining \
16  --cast-all \
17  --gufa-optimizing \
18  input.wasm -o optimizado.wasm
19
20# Verificar la diferencia de tamaño
21ls -la input.wasm optimizado.wasm
22
23# Esperado: 1.5-2x más pequeño después de la optimización
24# Esperado: 1.9x de mejora promedio en velocidad de ejecución (según benchmarks del equipo de V8)

Limitaciones y consideraciones

A pesar de su potencial transformador, WasmGC tiene limitaciones importantes que debes conocer:

Limitaciones actuales

  • Sin punteros interiores: No puedes crear una referencia a un campo dentro de un struct — solo al struct completo. Esta es la razón por la que .NET no puede adoptar WasmGC v1.
  • Sin finalización: No hay equivalente al finalize() de Java o al IDisposable de C# activado por el GC. Los recursos deben gestionarse explícitamente.
  • Sin referencias débiles en Wasm: Aunque JavaScript tiene WeakRef, WasmGC v1 no expone capacidades de referencias débiles.
  • Sin control de GC concurrente: Los módulos Wasm no pueden sugerir ni controlar cuándo se ejecuta el GC — depende completamente de la VM del host.
  • Bugs específicos de navegadores: El renderizador Wasm de Flutter tiene problemas en Safari y Firefox a abril de 2026, a pesar de que WasmGC en sí funciona correctamente.

Cuándo NO usar WasmGC

  • Código C/C++/Rust: Estos lenguajes gestionan la memoria manualmente y deben seguir usando Wasm con memoria lineal
  • .NET/Blazor: Las incompatibilidades fundamentales hacen que WasmGC sea impracticable para el runtime de .NET
  • Aplicaciones en tiempo real que requieren control de pausas del GC: No puedes ajustar el GC para cargas de trabajo sensibles a la latencia

Ejemplo completo: aplicación con detección de soporte

Aquí tienes un ejemplo práctico de una página HTML que detecta WasmGC y carga la versión apropiada de la aplicación:

html
1<!DOCTYPE html>
2<html lang="es">
3<head>
4  <meta charset="UTF-8">
5  <title>Aplicación WasmGC</title>
6</head>
7<body>
8  <div id="root"></div>
9  <script type="module">
10    // Detección de funcionalidad
11    async function soportaWasmGC() {
12      try {
13        const bytes = new Uint8Array([
14          0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
15          0x01, 0x07, 0x01, 0x5f, 0x01, 0x00, 0x7f,
16        ]);
17        await WebAssembly.compile(new WebAssembly.Module(bytes));
18        return true;
19      } catch {
20        return false;
21      }
22    }
23
24    if (await soportaWasmGC()) {
25      // Cargar aplicación compilada con WasmGC
26      const { default: init } = await import('./app.wasm.js');
27      await init();
28      console.log('Ejecutando con WasmGC - GC nativo del navegador');
29    } else {
30      // Fallback a versión JavaScript
31      const { default: init } = await import('./app.js');
32      await init();
33      console.log('Ejecutando fallback de JavaScript');
34    }
35  </script>
36</body>
37</html>

Referencias y lecturas adicionales

Share:
CV

Cristhian Villegas

Software Engineer specializing in Java, Spring Boot, Angular & AWS. Building scalable distributed systems with clean architecture.

Comments

Sign in to leave a comment

No comments yet. Be the first!

Related Articles

Stay updated

Get notified when I publish new articles. No spam, unsubscribe anytime.