A Cloudflare anunciou a primeira prévia experimental pública do suporte ao alvo de compilação wasm32-unknown-emscripten na cadeia de ferramentas wasm-bindgen e no ambiente Rust Workers. Esse caminho permite compilar e executar um número maior de aplicações e bibliotecas Rust nativas em WebAssembly na plataforma global Workers, em vez de se limitar às bibliotecas previamente compatíveis com o modelo tradicional do WebAssembly.
Esse trabalho representa uma integração entre o Emscripten, que fornece uma camada para conectar código nativo ao ambiente web e simular funções como sistema de arquivos, temporizadores e sockets, e o wasm-bindgen, responsável por criar bindings entre Rust e JavaScript. Com as novas mudanças, tanto o compilador Rust quanto o compilador Emscripten podem usar a camada de bindings do outro no mesmo processo de compilação.
Ampliação da compatibilidade das bibliotecas Rust
A Cloudflare afirma que os testes iniciais mostraram melhor compatibilidade com bibliotecas Rust, incluindo bibliotecas de baixo nível. Bibliotecas como libc, socket2 e Mio precisaram de alterações limitadas para adicionar o alvo Emscripten às condições da plataforma. A biblioteca mais complexa foi o Tokio, porque o Workers opera com uma única thread dentro de um loop de eventos JavaScript, enquanto o Tokio tradicionalmente depende da suspensão da thread durante a espera por operações de entrada e saída.
Para lidar com essa diferença, a Cloudflare trabalha em duas abordagens. A primeira usa a WebAssembly JavaScript Promise Integration, que permite suspender a pilha WebAssembly e devolver o controle ao loop de eventos JavaScript. Isso exige uma gestão cuidadosa do contexto local da thread ao suspender e retomar as pilhas. A segunda abordagem propõe um padrão LocalEventLoop para o Tokio, no qual as tarefas prontas são executadas por meio de uma operação drive(), e a espera é substituída por um sinal de notificação ao loop de eventos do host.
Suporte a sockets e redes TCP
O suporte a redes foi outro desafio, pois o Tokio depende de epoll_wait() por meio do Mio, enquanto o Emscripten oferecia suporte limitado a poll() e uma camada para simular WebSocket. Por isso, a Cloudflare contribuiu com mais de 40 pull requests para o Emscripten a fim de adicionar a camada -sNODERAWSOCKETS, que fornece suporte a epoll, TCP, UDP e Unix sockets por meio da interface node:net.
Como o Workers oferece compatibilidade com as interfaces do Node.js, a mesma ponte pode ser usada dentro da plataforma, sem adicionar interfaces personalizadas separadas entre Emscripten e Cloudflare. Esses recursos continuam experimentais, e alguns patches do Tokio ainda estão em revisão antes de serem integrados definitivamente ao projeto.
Teste prático com um servidor Minecraft
Para testar o nível de compatibilidade, o engenheiro da Cloudflare Dan Lapid executou dentro de um Durable Object o servidor Minecraft escrito em Rust, conhecido como Pumpkin. Como o Durable Object opera com uma única thread, os loops do jogo, o agendamento das regiões e as tarefas do Rayon foram convertidos em tarefas cooperativas dentro de um loop do Tokio, em vez de depender de threads independentes do sistema operacional.
O servidor usou o sistema de arquivos por meio das interfaces do Node.js, armazenando os arquivos no SQLite do Durable Object através da biblioteca worker-fs-mount. As conexões dos jogadores também passaram por um TCP ingress e depois foram encaminhadas para um servidor TCP dentro do objeto. Segundo a Cloudflare, isso permitiu executar um servidor Minecraft multijogador com persistência do estado e reinicialização do objeto a partir do mundo armazenado.
Por que esse avanço é importante?
O valor prático da mudança não está apenas na adição de um novo alvo de compilação, mas na redução do número de bibliotecas e aplicações que precisam ser reescritas para funcionar no Workers. No entanto, a Cloudflare descreve o suporte como experimental e pré-lançamento, e o novo design do Tokio, o suporte a JSPI e algumas integrações do Emscripten ainda estão em desenvolvimento e revisão upstream. Portanto, o caminho abre espaço para experimentos com a execução de aplicações Rust nativas, mas ainda não comprova ser uma alternativa completa e estável para todos os ambientes tradicionais de execução.