Pacotes populares
A conformidade com a especificação não garante que bibliotecas reais funcionem. Mecanismos JS que passam em 99 % do test262 ainda falham com frequência em código de produção porque as bibliotecas dependem de uma longa lista de "casos extremos da especificação" — traps de Proxy em ordens específicas, formato de Function.prototype.toString, comportamento de regex com entradas difíceis e a interação exata entre a ordenação de Object.keys e nomes de propriedades computados.
O Phasis verifica 204 bibliotecas amplamente utilizadas, comparando-as byte a byte com Node.js (V8). Elas ficam em tests/Popular/ no repositório, e o CI as executa sempre que o código-fonte do mecanismo ou o conjunto de testes muda.
Cobertura por categoria
| Categoria | Bibliotecas |
|---|---|
| Analisadores / AST | acorn 8.16.0, chevrotain 11.0.3, parse5 7.2.1, parsimmon 1.18.1, jsep 1.4.0, postcss-value-parser 4.2.0, acorn-walk 8.3.4, estraverse 5.3.0, escodegen 2.1.0, css-tree 3.0.4, sax 1.4.1, nearley 2.20.1 |
| Templates / Markdown / HTML | mustache 4.2.0, handlebars 4.7.9, marked 18.0.3, markdown-it 14.1.0 (+ markdown-it-emoji), markdown-table 3.0.4, showdown 2.1.0, cheerio 1.1.2, htmlparser2 11.0.0 |
| Utilitários / Funcional | lodash 4.18.1, ramda 0.31.3, remeda 2.17.4, es-toolkit 1.27.0, immutable 5.1.3, immer 10.1.1, redux 5.0.1, deepmerge 4.3.1, dot-object 2.1.5, lodash.merge 4.6.2, lodash.clonedeep 4.5.0, extend 3.0.2, extend-shallow 3.0.2, mixin-deep 2.0.1, merge-options 3.0.4 |
| Acesso a objetos | dequal 2.0.3, clsx 2.1.1, classnames 2.5.1, get-value 4.0.1, set-value 4.1.0, object.omit 3.0.0, object.pick 1.3.0, is-plain-obj 4.1.0, kind-of 6.0.3 |
| Validação / Esquema | zod 4.4.3, yup 1.4.0, valibot 1.1.0, superstruct 2.0.2, validator 13.12.0, email-validator 2.0.4, ajv 8.17.1, @sinclair/typebox 0.34.42, runtypes 6.7.0, typanion 3.14.0, ow 2.0.0 |
| Data / hora | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| Matemática / números | bignumber.js 11.1.1, decimal.js 10.6.0, numeral 2.0.6, jsbi 4.3.0, big.js 6.2.2, fraction.js 4.3.7, complex.js 2.4.2, simple-statistics 7.8.8 |
| Hash / criptografia | blueimp-md5 2.19.0, crypto-js 4.2.0, fnv-plus 1.3.1, murmurhash3js 3.0.1, hash-sum 2.0.0, jwt-decode 4.0.0, @noble/hashes 2.2.0, tweetnacl 1.0.3, aes-js 3.1.2, bcryptjs 3.0.2, xxhashjs 0.2.2, object-hash 3.0.0 |
| Pesquisa / diff | fuse.js 7.3.0, minisearch 7.1.1, diff 8.0.2, diff-match-patch 1.0.5, fast-deep-equal 3.1.3, fast-equals 5.2.2, fastest-levenshtein 1.0.16, lunr 2.3.9 |
| JSON / formatos de dados | json5 2.2.3, js-yaml 4.1.0, yaml 2.6.1, toml 3.0.0, smol-toml 1.3.1, fast-json-patch 3.1.1, jmespath 0.16.0, jsonata 2.0.6, jsonpath-plus 10.3.0, mingo 6.7.0, sift 17.1.3, fast-json-stable-stringify 2.1.0, safe-stable-stringify 2.5.0, json-stringify-safe 5.0.1, canonicalize 2.1.0, papaparse 5.5.4 |
| Strings / linguística | he 1.2.0, slugify 1.6.9, camelcase 8.0.0, entities 6.0.1, pluralize 8.0.0, inflection 3.0.2, wcwidth 1.0.1, emoji-regex 10.4.0, unraw 3.0.0, jsesc 3.1.0, lower-case 2.0.2, upper-case 2.0.2, dot-case 3.0.4, pascal-case 3.1.2, snake-case 3.0.4, title-case 3.0.3, xregexp 5.1.1, escape-string-regexp 5.0.0, ansi-regex 6.1.0, strip-ansi 7.1.2, string-width 8.1.0 |
| URL / web | url-parse 1.5.10, qs 6.13.1, query-string 9.1.1, tldts 6.1.69, punycode 2.3.1, linkifyjs 4.3.1, ipaddr.js 2.2.0, uri-js 4.4.1, url-template 3.1.1, bowser 2.11.0 |
| Compactação / codificação / arquivos | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| Cor | color-string 2.1.1, d3-color 3.1.0, chroma-js 3.1.2, color-name 2.0.0, tinycolor2 1.6.0, color 5.0.3 |
| Cópia / igualdade | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| Formato / exibição | ms 2.1.3, bytes 3.1.2 |
| IDs / UUIDs | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| Detecção de tipos / glob | type-detect 4.1.0, picomatch 4.0.2, minimatch 10.1.1, wildcard-match 5.1.4, glob-to-regexp 0.4.1, to-regex 4.0.4, array-uniq 3.0.0, array-unique 0.3.2 |
| Semver / configuração | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| Caches / desempenho | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| Assíncrono / eventos | eventemitter3 5.0.1, eventemitter2 6.4.10, mitt 3.0.1, p-limit 7.1.1, p-queue 9.0.2, p-defer 5.0.0, p-retry 7.1.0, throttle-debounce 5.0.2, async 3.2.6 |
| Estado reativo | mobx 6.13.7, xstate 5.23.0, valtio 2.1.5, nanostores 1.0.1, jotai 2.16.1, redux-saga 1.3.0, redux 5.0.1 |
| CSS / estilos | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| Build / AST / compiladores | magic-string 0.30.20, escodegen 2.1.0, acorn-walk 8.3.4, estraverse 5.3.0, @babel/parser 7.28.5, terser 5.46.0, prettier 3.3.3, svelte 5.55.7 (compiler), typescript 6.0.3 |
| MQTT / protocolo | mqtt-packet 9.0.4 |
| GraphQL | graphql-js 16.11.0 |
| Realce de sintaxe | highlight.js 11.11.1 |
| Testes / asserções | chai 6.2.1 |
Total: 204 bibliotecas reproduzem exatamente a saída do Node. Todas estão fixadas na versão upstream mais recente disponível na última atualização.
Como funciona
Cada cenário é um diretório tests/Popular/<lib>/ com três arquivos:
tests/Popular/lodash/
├── lodash.js ← vendored upstream library (untouched, UMD bundle)
├── runner.js ← Phasis-side script that exercises the library
└── oracle.txt ← Node.js output of running runner.js (committed)
tests/Popular/PopularPackagesTest.php é um teste PHPUnit com provedor de dados que:
- Carrega
lodash.js+runner.jsem umnew Phasis\Engine()novo. - Captura a saída de
console.logem um buffer. - Verifica se o buffer capturado é idêntico byte a byte ao
oracle.txt.
Gere novamente um oráculo com:
node tests/Popular/gen-oracle.js tests/Popular/<lib>
(Usado ao atualizar a biblioteca incorporada — executa novamente o runner no Node real e substitui oracle.txt.)
Controle do CI
Workflow: .github/workflows/popular.yml.
Executa em pushes e pull requests para main que alterem src/, tests/Popular/, phpunit.xml.dist, os arquivos Composer ou o próprio workflow, além de execuções manuais. Duas etapas:
- Lado Phasis — executa a suíte de testes PHPUnit
popular, que executa cada biblioteca por meio de Phasis e compara os resultados com o oráculo versionado. Falha se um único byte for diferente. - Nova verificação no Node — executa
node tests/Popular/gen-oracle.js …com cada biblioteca e confirma que o oráculo recém-gerado corresponde ao que está no repositório. Detecta alterações causadas por "atualização da biblioteca incorporada sem atualizar o oráculo".
Ambas precisam passar antes da integração do PR. Uma melhoria em test262 que prejudique o lodash não é aceitável; uma melhoria no lodash que prejudique test262 também não.
Por que estas bibliotecas
- acorn — a análise sintática é a parte mais frágil de qualquer mecanismo JS. Ela exercita todos os casos extremos de sintaxe que o JS moderno acrescenta. Se Phasis consegue analisar código moderno arbitrário com acorn, o runtime é sólido.
- mustache.js — a criação de templates é um dos casos de uso de incorporação que o Phasis visa explicitamente (o primeiro exemplo concreto do README são "mecanismos de templates"). Mustache exercita iteração, resolução de escopo e transformações de strings na ordem usada por templates reais.
- lodash — a biblioteca utilitária JS mais usada no mundo. Suas mais de 300 funções acessam indiretamente todos os métodos da biblioteca padrão. Se o lodash funciona, a transformação genérica de dados JS funciona.
- marked — renderização de Markdown. É prático e exercita regex (muito) e manipulação de strings com estado entre linhas. Revela diferenças entre o mecanismo de regex do PCRE2 (fallback do Phasis) e o Irregexp do V8.
- dayjs — a aritmética de datas e horários é uma fonte clássica de erros de um dia que nenhum caso de test262 detecta. dayjs cobre variantes de construtores, operações aritméticas que atravessam limites de meses equivalentes ao horário de verão e expansão de tokens de formatação nos mesmos caminhos de código usados por praticamente todas as bibliotecas de Date do JS.
- bignumber.js — a aritmética de precisão arbitrária sem TypedArrays exercita a análise de números baseada em strings, laços de multiplicação e divisão de inteiros grandes e seleção do modo de arredondamento — tudo em JS puro, portanto o mecanismo arca com todo o custo. Revela qualquer falha sutil na conversão entre Number e String.
- json5 — a análise sintática de JSON flexível depende bastante de regexes de classes de caracteres e tokenização com estado. É um bom teste de alerta para a correção de regexes e os limites da iteração por strings.
- fuse.js — um UMD transpilado pelo Babel que exercita
_classCallCheck(o padrãothis instanceof Ctorusado por todas as classes transpiladas antes do ES6), além do algoritmo bitap completo de busca aproximada. Tem o formato compartilhado por todo tipo de biblioteca transpilada pelo Babel; assim, qualquer problema que afete o Fuse afeta metade do ecossistema npm. - handlebars — criação completa de templates com compilação seguida de renderização. Exercita o caminho de runtime sem
evalpor meio de uma única entradacompile()enorme, travessia da AST, despacho de helpers por uma tabela de busca dinâmica e verificação de marca deSafeStringque usainstanceofentre realms. É um contraponto ao percurso mais simples de templates do mustache.js. - zod — validação de esquemas em runtime. Hierarquias extensas de classes (
ZodString,ZodObject,ZodArray,ZodUnion, …) com encadeamento de métodos que retorna subclasses refinadas; formatação estruturada de erros em que o formato do array.issuesdo lado do JS precisa corresponder byte a byte ao Node; e padrões de discriminadores e tags literais. Testa o tipo de código de validação fortemente orientado a objetos que envolve metade dos aplicativos modernos TypeScript. - typescript — o compilador TypeScript real em execução no mecanismo incorporado. São 9 MB de compilador minificado que reanalisa TS arbitrário, percorre a AST e emite JS — a carga útil JS pura mais pesada que se pode imaginar. Se Phasis consegue transpilar generics, async/await, enums e hierarquias de classes com resultado byte a byte idêntico ao de
tsc, a semântica da linguagem é sólida. - prettier — formatador de JS opinativo. Formatar JS com JS exercita todos os casos extremos da especificação do mecanismo pelo mesmo fluxo de controle que formata seu código — uma carga de trabalho excepcionalmente exigente.
- svelte/compiler — compilador independente do Svelte. Analisa código-fonte
.svelte, percorre a AST e emite JS para destinos client e SSR. - terser / @babel/parser / postcss — minificador JS, analisador JS, pós-processador CSS. Dezenas de milhares de linhas de código minificado que reanalisam entradas arbitrárias — a superfície em que surgem estruturas de AST raras.
- ajv — validador de esquemas JSON que compila cada esquema JIT em uma função validadora personalizada por meio de
new Function(...). Exercita o caminho do construtor Function, usado pela maioria das bibliotecas de esquemas e templates. - mobx — estado reativo baseado em proxy. Cada leitura de um observável passa por uma armadilha Proxy
getque registra uma dependência; cada gravação dispara reações. Um teste de estresse para a infraestrutura Proxy, Maps observáveis / arrays / objetos aninhados e o agendador autorun. - cheerio / htmlparser2 — jQuery do lado do servidor sobre um analisador rápido HTML. Análise pelo mecanismo de seletores, travessia no estilo DOM, manipulação de atributos e serialização HTML em um só pacote.
- graphql-js / jsonata — implementação de referência GraphQL e uma linguagem de consulta JSON. Ambas fazem uso intenso de esquemas, validação e avaliadores recursivos — código típico de «camada de dados no navegador».
- JSZip — criador assíncrono de arquivos ZIP. Encaminha o trabalho por meio do agendamento orientado a
setImmediatee produz saída binária real, exercitando tanto a superfície de temporizadores quanto caminhos com uso intenso deUint8Array. - moment / luxon — operações aritméticas com datas e horários. moment é um UMD mutável e ajustado manualmente; luxon é a reescrita imutável moderna. Juntas, cobrem toda a superfície de formatação, análise e cálculos de meses/anos equivalentes entre fusos horários.
- mqtt-packet — codec MQTT JS / 5.0 puro de 3.1.1. Empacotamento e decodificação em nível de byte, além de classes de caracteres de regex para caracteres fora do alfabeto base64, que exercitam casos extremos da gramática do Annex-B.
- xstate / valtio / nanostores / jotai / redux-saga — a variedade moderna de gerenciamento de estado. Máquinas de estado, estado proxy, armazenamentos de átomos, átomos derivados e executores de efeitos baseados em geradores — cada biblioteca aborda um formato diferente de reatividade.
- escodegen / acorn-walk / estraverse / magic-string — ferramentas de AST. Geração e travessia de código, além de edição não destrutiva do código-fonte — os componentes básicos de qualquer transformador de JS em JS (ferramentas de build, codemods, linters).
- papaparse / lunr / yaml / sax / css-tree — analisadores e tokenizadores puros. CSV, índice de pesquisa de texto completo, YAML 1.2, análise em fluxo no estilo SAX XML e AST de CSS. Gramáticas diferentes, todas boas sentinelas para a varredura em nível de caractere e o comportamento de regex.
Adicionando mais
Adicione um novo diretório em tests/Popular/<name>/ com a estrutura de três arquivos e, em seguida:
node tests/Popular/gen-oracle.js tests/Popular/<name> # one-time, generates oracle.txt
git add tests/Popular/<name>
A suíte PHPUnit o detecta automaticamente na próxima execução, e o CI o inclui porque a alteração afeta tests/Popular/.
Bons candidatos para adicionar: chevrotain (combinador de analisadores, exercita closures + regex), nanoid (limite de criptografia/aleatoriedade), date-fns (suporte a fusos horários além do dayjs).