Pacotes npm reais agora compilam: axios, zod, express — e uma varredura de conformidade
O último post terminou em v0.5.875 com a história do GC — fechando o gap que o benchmark de aya_koto expôs. Aquele post era sobre vencer um benchmark. Este é sobre um tipo de trabalho diferente: as cerca de 270 releases entre v0.5.875 e v0.5.1146, aterrissadas ao longo de cerca de quatro semanas, quase nenhuma delas sendo manchete de benchmark. O tema mudou de “ir rápido num microbenchmark” para “fazer TypeScript do mundo real e pacotes npm reais de fato compilarem e rodarem.” Mais uma revisão visual completa do Windows e uma pilha de novos widgets pelo caminho.
Eis o que saiu, agrupado pelo que de fato servia.
Pacotes npm reais compilam agora
O maior fio único através desta janela é uma varredura para fazer pacotes npm populares compilarem para binários nativos e passarem em testes comportamentais — não apenas “linkar sem erros,” mas rodar e produzir a saída certa. A lista que agora funciona através de perry.compilePackages inclui axios, jose, zod v4, vitest, express, fastify, @hono/node-server, dayjs, chalk, ms, debug, lodash, ethers, argon2, e Colyseus.
Cada um falhava por sua própria razão, e cada fix é sua própria pequena história:
- zod v4 crashava com
Cannot read properties of undefined (reading 'onattach'). Causa raiz (v0.5.1144, #4698):new F()ondeFé uma função importada de outro módulo silenciosamente produzia um objeto vazio — o corpo do construtor nunca rodava, então toda checagem estilo$ZodCheckMinLengthvoltava despida de sua propriedade_zod. - axios + jose precisavam de crypto e compressão que Perry ainda não tinha:
zlib.createBrotliDecompress,crypto.subtle.wrapKey/unwrapKey,subtle.generateKey/encrypt/decryptpara AES-GCM, erandomFillSync(v0.5.972–976). - fastify estava em deadlock num timeout de polling de um segundo em
wait_for_promise; o substituímos por uma espera com condvar e fizemos promises rejeitadas aparecerem comoHTTP 500em vez de travar (v0.5.912). - @hono/node-server não conseguia ler um body de POST —
c.req.text()/.json()/.formData()retornavam vazio em POST/PUT até um fix de registro de pai em v0.5.1142. - chalk, ms, debug, express todos batiam no mesmo formato: um valor chamável com propriedades anexadas (
chalk.red,express()maisexpress.Router). Três variações desse padrão foram corrigidas ao longo de v0.5.935 e da varredura npm ao redor, maisutil.inherits+ um scaffold de prototype de stream para destravar express (v0.5.990). - dayjs, distribuído como um bundle minificado, exercitava o dispatch de método de prototype JS-clássico (
Class.prototype.m = fn) que Perry lowereava errado (v0.5.924/932).
Por baixo de tudo isso está a parte que faz pacotes que Perry não consegue compilar nativamente ainda rodarem: o runtime de fallback V8 ficou real nesta janela. Seu ModuleLoader agora lê de um mapa de módulos embutido, então um binário de fallback ainda é autossuficiente — sem node_modules soltos em runtime (v0.5.994). createServer faz ponte para um servidor hyper real (v0.5.999), e os globais Web Fetch Response / Request / Headers existem no caminho de fallback (v0.5.1006). E o import() dinâmico em tempo de compilação — await import('./foo.ts') com string literal resolvido em tempo de build — finalmente aterrissou (v0.5.905, #100).
Uma varredura de conformidade test262
O outro fio dominante é a conformidade. Rodamos passes focados contra os radares do subconjunto test262 e movemos o ponteiro nos built-ins em que código real mais se apoia:
built-ins/String 60.2% → 79.3% (v0.5.1128)
built-ins/Array 61.5% → 72.5% (v0.5.1127)
language/.../destructuring 41.6% → 53.9% (v0.5.1143)O salto de String veio de dar a todo método de String.prototype dispatch genérico de this e corrigir a coerção de índice de slice/substring. O salto de Array foi thisArg nos callbacks de array denso (forEach/map/filter/…), ToLength array-like, ordenação de operações da spec, e validação de zero argumentos. Destructuring ganhou destructuring de parâmetros em métodos de classe plain, generator, async-generator, static, e private.
Ao lado dos números de manchete, uma longa cauda de correção aterrissou: JSON.parse agora lança um SyntaxError real (não um TypeError) e rejeita tokens à direita; seu reviver caminha via o algoritmo da spec InternalizeJSONProperty; Object.prototype.toString branda corretamente para typed arrays, Symbol, BigInt, Map/Set/WeakMap/WeakSet/Promise/RegExp; RegExp.prototype.toString retorna /source/flags; async generators acertaram sua semântica de yield-aguarda-operando. Estes são radares de subconjunto, não a suíte completa — Perry ainda está escalando — mas a escalada deste mês foi íngreme.
Windows fica Fluent
O Windows ganhou uma revisão visual (a série #4681). Janelas de Perry agora optam pela chrome DWM moderna por padrão — backdrop Mica, cantos arredondados, e uma barra de título com consciência de tema — e os controles comuns renderizam através do comctl32 v6 em vez dos defaults da era Windows 95. O window proc agora trata WM_DPICHANGED, então uma janela permanece nítida quando você a arrasta entre monitores com escala mista em vez de ficar esticada por bitmap.
Crucialmente, nada disso reintroduziu a antiga regressão #1542 de “área preta após resize”: a área cliente ainda é pintada opaca, e o blur-through Mica/Acrylic de quadro completo permanece um opt-in explícito via app.setVibrancy(...). Há também um novo scaffold de backend --target windows-winui (WinUI 3) para apps que querem o stack totalmente moderno, e um fix pequeno mas real que faz perry compile main.ts -o main produzir main.exe no Windows para que o PowerShell de fato o lance (v0.5.1146).
Novos widgets, em toda plataforma
Dois widgets aterrissaram só no último dia, e ambos abrangem toda plataforma de UI que Perry mira:
- DatePicker (#4772) — um controle de data compacto, estilo campo:
NSDatePickerno macOS,UIDatePicker(.compact) no iOS/visionOS,SysDateTimePick32no Windows,android.widget.DatePickerno Android, GTK4 no Linux. Uma superfície TS para todos eles. - Drag & drop (#4773) — qualquer widget pode ser um destino de drop e uma fonte de drag para text/files/URLs, mapeado para
NSDraggingDestination(AppKit),UIDropInteraction(UIKit), eView.setOnDragListener(Android).
import { DatePicker } from "@perry/ui";
DatePicker(2026, 6, (iso) => {
// iso is a POSIX-locale "yyyy-MM-dd" string
console.log("picked", iso);
});Mais cedo na janela a prateleira de widgets também se preencheu por desktop e mobile — Combobox, TreeView, Calendar, Chart, CommandPalette, RichTextEditor, MapView, PdfView, BottomNavigation, e uma ImageGallery com swipe — cada um respaldado pelo controle nativo real em toda plataforma. O HarmonyOS (ArkTS) ganhou Chart e TreeView (v0.5.893), os dois últimos widgets que precisava para alcançar paridade com os outros.
GC, internals, e estabilidade
A maioria dessas 270 releases não são manchetes — são correções de bug e internals, e esse é o ponto desta fase. Algumas que vale destacar:
- O GC continuou. O trabalho de free list condicional do post do GC continuou se assentando, e uma classe aguda de bug foi fechada: Promises com ponte nativa agora são fixadas enquanto em voo num worker tokio para que o GC não possa varrê-las antes da resolução aterrissar (v0.5.923). Se você rodou um fetch async sob carga e viu uma coleta fantasma, era isto.
- O modelo de memória está documentado. Há agora um mergulho profundo
internals/memory-model.md— NaN-boxing, o GC geracional, a shadow stack, e write barriers — ligado ao site de docs (v0.5.933). - Uma onda de fixes de estabilidade de codegen aflorou pela varredura npm: uma arrow
constem nível de módulo chamada dentro de um passo async retomado não dá mais SIGSEGV (v0.5.953),try { await rejected } catch { return X }não trava mais para sempre (v0.5.870), e um punhado de crashes dejs_is_truthy/ range de ponteiro cru que bundles reais disparavam.
Faxina da Apple
Menor mas real: perry setup ios --development agora provisiona para builds de desenvolvimento (v0.5.1023), e o caminho de build/link de bibliotecas cruzadas da Apple foi deduplicado e tornado portável quanto à largura de ponteiro (v0.5.1121/1125) — que é o que destravou a matriz de publicação npm / Homebrew / APT / winget que estava emperrada.
Onde isso deixa as coisas
A aposta por trás de Perry sempre foi que “TypeScript nativo” só importa se TypeScript real rodar — não um subconjunto de brinquedo, os pacotes de verdade que as pessoas dão npm install. Este mês foi principalmente esse trabalho: menos um número único para se gabar, mais um empurrão longo e sem glamour para fechar o gap entre “compila” e “funciona.” Os radares de conformidade e os testes de paridade npm são o placar que estamos observando agora, e vamos continuar postando os números — os bons e os ainda imperfeitos.
Source: github.com/PerryTS/perry — Issues: github.com/PerryTS/perry/issues
— Ralph
Gostou deste post? Receba o próximo.
Notas curtas sobre os releases do Perry e o que vem por aí.
Poucos e-mails por mês. Cancele a qualquer momento.