
# 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:

```text
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:

1. Carga `lodash.js` + `runner.js` en un `new Phasis\Engine()` nuevo.
2. Captura la salida de `console.log` en un búfer.
3. Comprueba que el búfer capturado sea idéntico byte por byte a `oracle.txt`.

Vuelve a generar un oráculo con:

```bash
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`](https://github.com/inline0/phasis/blob/main/.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:

1. **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.
2. **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ón `this instanceof Ctor` que 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 entrada `compile()` enorme, el recorrido del AST, la selección de helpers mediante una tabla de búsqueda dinámica y la comprobación de marca de `SafeString`, que usa `instanceof` entre 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 `.issues` del 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 `get` que 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 `setImmediate` y genera datos binarios reales, lo que comprueba tanto la superficie de temporizadores como las rutas con mucho `Uint8Array`.
- **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:

```bash
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).
