Paquetes populares
La conformidad con la especificación no garantiza que funcionen las bibliotecas reales. Los motores JS que superan el 99 % de test262 aún suelen fallar con código de producción porque las bibliotecas dependen de muchos «casos límite de la especificación»: trampas de Proxy en órdenes concretos, la forma de Function.prototype.toString, el comportamiento de las expresiones regulares con entradas complejas y la interacción exacta entre el orden de Object.keys y los nombres de propiedades calculados.
Phasis verifica 204 bibliotecas de uso extendido byte a byte frente a Node.js (V8). Están en tests/Popular/ del repositorio y CI las ejecuta cada vez que cambia el código fuente del motor o la suite.
Cobertura por categoría
| Categoría | Bibliotecas |
|---|---|
| Analizadores / 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 |
| Plantillas / 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 |
| Utilidades / funcionales | 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 |
| Acceso 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 |
| Validación / 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 |
| Fecha / hora | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| Matemáticas / 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 |
| Hashing / criptografía | 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 |
| Búsqueda / diferencias | 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 datos | 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 |
| Cadenas / lingüí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 |
| Compresión / codificación / archivo | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| Color | 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 |
| Clonación / igualdad | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| Formato / visualización | ms 2.1.3, bytes 3.1.2 |
| Identificadores / UUID | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| Detección 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 / configuración | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| Cachés / rendimiento | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| Así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 reactivo | 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 |
| Compilación / 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 (compilador), typescript 6.0.3 |
| MQTT / protocolo | mqtt-packet 9.0.4 |
| GraphQL | graphql-js 16.11.0 |
| Resaltado de sintaxis | highlight.js 11.11.1 |
| Pruebas / aserciones | chai 6.2.1 |
Total: 204 bibliotecas reproducen exactamente el resultado de Node. Todas están fijadas a la última versión del upstream en el momento de la última actualización.
Cómo funciona
Cada escenario es un directorio tests/Popular/<lib>/ con tres archivos:
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 es una prueba de proveedor de datos PHPUnit que:
- Carga
lodash.js+runner.jsen unnew Phasis\Engine()nuevo. - Captura la salida de
console.logen un búfer. - Comprueba que el búfer capturado sea idéntico byte por byte a
oracle.txt.
Vuelve a generar un oráculo con:
node tests/Popular/gen-oracle.js tests/Popular/<lib>
(Se usa al actualizar la biblioteca incluida; vuelve a ejecutar el ejecutor con Node real y sobrescribe oracle.txt.)
Control de CI
Flujo de trabajo: .github/workflows/popular.yml.
Se ejecuta con los envíos y las solicitudes de incorporación de cambios a main que modifiquen src/, tests/Popular/, phpunit.xml.dist, los archivos Composer o el propio flujo de trabajo, y también mediante ejecución manual. Consta de dos pasos:
- Lado Phasis — ejecuta la suite de pruebas PHPUnit
popular, que ejecuta cada biblioteca mediante Phasis y compara los resultados con el oráculo confirmado en el repositorio. Falla si difiere un solo byte. - Verificación de Node — ejecuta
node tests/Popular/gen-oracle.js …con cada biblioteca y comprueba que el oráculo recién generado coincida con el incluido en el repositorio. Detecta cambios cuando «se actualizó una biblioteca incluida sin actualizar el oráculo».
Ambos deben pasar antes de fusionar la solicitud de incorporación de cambios. No sirve que test262 pase si se rompe lodash, ni que pase lodash si se rompe test262.
Por qué estas bibliotecas
- acorn — el análisis es la parte más frágil de cualquier motor JS. Comprueba todos los casos límite sintácticos que incorpora JS moderno. Si Phasis puede analizar código moderno arbitrario con acorn, el entorno de ejecución es sólido.
- mustache.js — las plantillas son uno de los casos de uso de integración a los que apunta explícitamente Phasis (el primer ejemplo concreto de README son los «motores de plantillas»). Mustache comprueba la iteración, la resolución de ámbitos y las transformaciones de cadenas en el orden en que las realizan las plantillas reales.
- lodash — la biblioteca de utilidades JS más usada del mundo. Sus más de 300 funciones llegan de forma transitiva a todos los métodos de la biblioteca estándar. Si lodash funciona, también funciona la transformación genérica de datos JS.
- marked — renderizado de Markdown. Es práctico y comprueba las expresiones regulares (muchas) y la manipulación de cadenas con estado entre líneas. Detecta diferencias en el motor de expresiones regulares entre PCRE2 (el fallback de Phasis) e Irregexp de V8.
- dayjs — la aritmética de fecha y hora es una fuente clásica de errores de desfase de un día que ningún caso de test262 detecta. dayjs comprueba variantes del constructor, operaciones entre límites de mes equivalentes con horario de verano y la expansión de tokens de formato en rutas de código que usa casi toda biblioteca de fechas de JS.
- bignumber.js — la aritmética de precisión arbitraria sin TypedArrays comprueba el análisis numérico basado en cadenas, los bucles de multiplicación y división de enteros grandes y la selección del modo de redondeo; todo en JS puro, por lo que el motor asume todo el coste. Detecta cualquier fallo sutil en la conversión de Number a String.
- json5 — el análisis flexible de JSON depende en gran medida de expresiones regulares con clases de caracteres y tokenización con estado. Es una buena prueba de referencia para comprobar tanto la corrección de las expresiones regulares como los casos límite al recorrer cadenas.
- fuse.js — un UMD transpilado con Babel que comprueba
_classCallCheck(el patrónthis instanceof Ctorque usa toda clase transpilada anterior a ES6) y el algoritmo completo de búsqueda difusa bitap. Es el tipo de estructura que comparten todas las bibliotecas transpiladas con Babel, así que cualquier fallo en Fuse afecta a la mitad del ecosistema npm. - handlebars — plantillas completas con compilación seguida de renderizado. Comprueba la ruta de ejecución sin
eval, desde una única entradacompile()enorme, el recorrido del AST, la selección de helpers mediante una tabla de búsqueda dinámica y la comprobación de marca deSafeString, que usainstanceofentre distintos entornos globales. Contrasta con el recorrido de plantillas más sencillo de mustache.js. - zod — validación de esquemas en tiempo de ejecución. Jerarquías de clases complejas (
ZodString,ZodObject,ZodArray,ZodUnion, …) con encadenamiento de métodos que devuelve subclases refinadas, formato estructurado de errores donde la estructura de la matriz.issuesdel lado de JS debe coincidir byte por byte con Node, y patrones de discriminador y etiquetas literales. Comprueba el código de validación con mucho uso de POO que emplea la mitad de las aplicaciones modernas de TypeScript. - typescript — el compilador real de TypeScript ejecutado en el motor integrado. Un compilador minificado de 9 MB que vuelve a analizar TS arbitrario, recorre el AST y genera JS: la carga útil pura de JS más pesada imaginable. Si Phasis puede transpilar genéricos, async/await, enumeraciones y jerarquías de clases con resultados idénticos byte por byte a
tsc, la semántica del lenguaje es sólida. - prettier — formateador de JS con criterios propios. Dar formato a JS con JS hace que el mismo flujo de control que da formato al código toque todos los casos límite de la especificación del motor; es una carga de trabajo excepcionalmente exigente.
- svelte/compiler — compilador independiente de Svelte. Analiza código fuente de
.svelte, recorre el AST y genera JS para el cliente y SSR. - terser / @babel/parser / postcss — minificador de JS, analizador de JS y posprocesador de CSS. Decenas de miles de líneas de código minificado que vuelven a analizar entradas arbitrarias: la superficie donde aparecen estructuras de AST poco comunes.
- ajv — validador de esquemas JSON que compila cada esquema JIT en una función de validación personalizada mediante
new Function(...). Comprueba la ruta del constructor Function que usan muchas bibliotecas de esquemas y plantillas. - mobx — estado reactivo basado en proxies. Cada lectura de un valor observable pasa por una trampa Proxy
getque registra una dependencia; cada escritura activa reacciones. Pone a prueba la infraestructura Proxy, los Mapas, las matrices y los objetos anidados observables, y el planificador de autorun. - cheerio / htmlparser2 — jQuery del lado del servidor sobre un analizador HTML rápido. Análisis del motor de selectores, recorrido al estilo del DOM, manipulación de atributos y serialización HTML en un solo paquete.
- graphql-js / jsonata — implementación de referencia de GraphQL y lenguaje de consulta JSON. Ambos usan mucho esquemas, validación y evaluadores recursivos, como el código típico de una «capa de datos en el navegador».
- JSZip — generador asíncrono de archivos ZIP. Gestiona el trabajo mediante la planificación basada en
setImmediatey genera datos binarios reales, lo que comprueba tanto la superficie de temporizadores como las rutas con muchoUint8Array. - moment / luxon — aritmética de fecha y hora. moment es un UMD mutable y optimizado a mano; luxon es su reescritura moderna e inmutable. Juntos cubren todo el ámbito del formato, el análisis y los cálculos de meses y años con zonas horarias equivalentes.
- mqtt-packet — códec MQTT / 5.0 3.1.1 puro de JS. El empaquetado y la decodificación a nivel de byte, además de las clases de caracteres de expresiones regulares para caracteres ajenos al alfabeto de base64, comprueban los casos límite de la gramática del Anexo B.
- xstate / valtio / nanostores / jotai / redux-saga — la variedad moderna de gestión de estado. Máquinas de estados, estado con proxy, almacenes de átomos, átomos derivados y ejecutores de efectos basados en generadores: cada biblioteca comprueba un tipo distinto de reactividad.
- escodegen / acorn-walk / estraverse / magic-string — herramientas para AST. Generación de código, recorrido y edición de código fuente sin alterar lo demás: los componentes básicos de cualquier transformador JS sobre JS (herramientas de compilación, codemods, linters).
- papaparse / lunr / yaml / sax / css-tree — analizadores y tokenizadores puros. CSV, índice de búsqueda de texto completo, YAML 1.2, XML de estilo SAX en flujo y AST de CSS. Gramáticas diferentes, todas buenas pruebas de referencia para el análisis carácter por carácter y el comportamiento de las expresiones regulares.
Añadir más
Añade un directorio nuevo dentro de tests/Popular/<name>/ con la estructura de tres archivos y luego:
node tests/Popular/gen-oracle.js tests/Popular/<name> # one-time, generates oracle.txt
git add tests/Popular/<name>
La suite PHPUnit lo detecta automáticamente en la siguiente ejecución, y CI lo incluye porque el cambio modifica tests/Popular/.
Candidatos interesantes que vale la pena añadir: chevrotain (combinador de analizadores; comprueba cierres y expresiones regulares), nanoid (límite de criptografía y aleatoriedad), date-fns (ámbito de zonas horarias más amplio que dayjs).