
# Pacchetti popolari

La conformità alle specifiche non garantisce il funzionamento delle librerie reali. Anche i motori JS che superano il 99 % di test262 spesso si guastano comunque con codice di produzione, perché le librerie dipendono da una lunga serie di "casi limite della specifica": trap Proxy in ordini specifici, forma di `Function.prototype.toString`, comportamento delle regex con input insidiosi e interazione precisa tra l'ordinamento di `Object.keys` e i nomi di proprietà calcolati.

Phasis verifica **204 librerie ampiamente utilizzate** byte per byte rispetto a Node.js (V8). Si trovano in `tests/Popular/` nel repository e CI le esegue ogni volta che cambiano il sorgente del motore o la suite.

## Copertura per categoria

| Categoria | Librerie |
|---|---|
| **Parser / 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 |
| **Template / 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à / funzionali** | 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 |
| **Accesso agli oggetti** | 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 |
| **Convalida / schemi** | 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 / ora** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Matematica / numeri** | 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 / crittografia** | 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 |
| **Ricerca / differenze** | 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 / formati dati** | 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 |
| **Stringhe / linguistica** | 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 |
| **Compressione / codifica / archivi** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Colori** | 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 |
| **Clonazione / uguaglianza** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Formato / visualizzazione** | ms 2.1.3, bytes 3.1.2 |
| **ID / UUID** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Rilevamento dei tipi / 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 / configurazione** | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| **Cache / prestazioni** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asincronia / eventi** | 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 |
| **Stato reattivo** | 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 / stili** | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| **Build / AST / compilatori** | 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 / protocollo** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Evidenziazione della sintassi** | highlight.js 11.11.1 |
| **Test / asserzioni** | chai 6.2.1 |

Totale: **204 librerie** riproducono esattamente l'output di Node. Tutte sono bloccate all'ultima versione upstream disponibile al momento dell'ultimo aggiornamento.

## Come funziona

Ogni scenario è una directory `tests/Popular/<lib>/` con tre file:

```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` è un test con provider di dati PHPUnit che:

1. Carica `lodash.js` + `runner.js` in un nuovo `new Phasis\Engine()`.
2. Acquisisce l'output di `console.log` in un buffer.
3. Verifica che il buffer acquisito sia identico byte per byte a `oracle.txt`.

Rigenerate un oracle con:

```bash
node tests/Popular/gen-oracle.js tests/Popular/<lib>
```

(Usato quando aggiornate la libreria vendorizzata: riesegue il runner con Node reale e sovrascrive `oracle.txt`.)

## Controllo CI

Workflow: [`.github/workflows/popular.yml`](https://github.com/inline0/phasis/blob/main/.github/workflows/popular.yml).

Viene eseguito su push e pull request a `main` che modificano `src/`, `tests/Popular/`, `phpunit.xml.dist`, i file Composer o il workflow stesso, e anche su avvio manuale. Due passaggi:

1. **Lato Phasis** — esegue la suite di test PHPUnit `popular`, che esegue ogni libreria tramite Phasis e confronta i risultati con l'oracle salvato nel repository. Fallisce se differisce anche un solo byte.
2. **Nuova verifica Node** — esegue `node tests/Popular/gen-oracle.js …` su ogni libreria e verifica che l'oracle appena rigenerato corrisponda a quello nel repository. Rileva le differenze dovute all'aggiornamento di una libreria vendorizzata senza aggiornare l'oracle.

Entrambi devono superare il controllo prima del merge della PR. Un miglioramento di test262 che rompe lodash non è accettabile; lo stesso vale per un miglioramento di lodash che rompe test262.

## Perché queste librerie

- **acorn** — il parsing è la parte più fragile di qualsiasi motore JS. Esercita ogni caso limite sintattico introdotto da JS moderno. Se Phasis riesce a fare il parsing di codice moderno arbitrario con acorn, il runtime è affidabile.
- **mustache.js** — il templating è uno dei casi d'uso di embedding a cui Phasis è specificamente rivolto (il primo esempio concreto del README è "motori di templating"). Mustache verifica iterazione, risoluzione degli scope e trasformazioni di stringhe nell'ordine usato dai template reali.
- **lodash** — la libreria di utilità JS più usata al mondo. Le sue oltre 300 funzioni toccano indirettamente ogni metodo della libreria standard. Se lodash funziona, funzionano anche le trasformazioni generiche dei dati JS.
- **marked** — rendering di Markdown. È un test pratico che esercita regex (in abbondanza) e manipolazione di stringhe con stato tra righe. Fa emergere le differenze del motore regex tra PCRE2 (il fallback di Phasis) e Irregexp di V8.
- **dayjs** — l'aritmetica di date e orari è una classica fonte di errori di un giorno che nessun caso test262 rileva. dayjs verifica varianti del costruttore, aritmetica attraverso i confini mensili equivalenti all'ora legale e l'espansione dei token di formattazione negli stessi percorsi di codice usati da qualsiasi libreria Date JS.
- **bignumber.js** — l'aritmetica a precisione arbitraria senza TypedArrays verifica il parsing dei numeri basato su stringhe, i cicli di moltiplicazione e divisione di interi grandi e la scelta della modalità di arrotondamento: tutto in JS puro, quindi il motore si fa carico dell'intero costo. Fa emergere qualsiasi sottile problema di conversione tra Number e String.
- **json5** — il parsing di JSON con sintassi permissiva si basa molto su regex di classi di caratteri e tokenizzazione con stato. È un ottimo test sentinella per la correttezza delle regex e i casi limite nell'iterazione delle stringhe.
- **fuse.js** — una UMD transpila da Babel che verifica `_classCallCheck` (il pattern `this instanceof Ctor` usato da ogni classe transpila prima di ES6) e l'intero algoritmo di fuzzy matching bitap. È una forma comune a ogni libreria transpila da Babel, perciò qualsiasi problema che rompe Fuse rompe metà dell'ecosistema npm.
- **handlebars** — templating completo con compilazione e rendering. Verifica il percorso runtime senza `eval` attraverso un'unica enorme entry `compile()`, l'attraversamento dell'AST, la gestione degli helper tramite una tabella di ricerca dinamica e il controllo del brand `SafeString` che usa `instanceof` tra realm. È un termine di paragone rispetto al più semplice attraversamento dei template di mustache.js.
- **zod** — convalida degli schemi a runtime. Gerarchie di classi articolate (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) con concatenamento di metodi che restituiscono sottoclassi raffinate, formattazione strutturata degli errori in cui la forma dell'array `.issues` lato JS deve corrispondere byte per byte a Node, e pattern con discriminatori e tag letterali. Verifica il codice di convalida con ampio uso di OO presente in metà delle app TypeScript moderne.
- **typescript** — il compilatore TypeScript *vero*, eseguito sul motore integrato. Un compilatore minificato di 9 MB che analizza nuovamente TS arbitrario, attraversa l'AST e genera JS: il carico JS puro più pesante immaginabile. Se Phasis riesce a transp ilare generics, async/await, enum e gerarchie di classi con output identico byte per byte a `tsc`, la semantica del linguaggio è corretta.
- **prettier** — formatter JS con scelte stilistiche precise. Formattare JS *con* JS significa esercitare ogni caso limite della specifica gestito dal motore attraverso lo stesso flusso di controllo usato per formattare il vostro codice: un carico di lavoro particolarmente impegnativo.
- **svelte/compiler** — il compilatore standalone di Svelte. Analizza il sorgente `.svelte`, attraversa l'AST e genera JS per gli ambienti client e SSR.
- **terser / @babel/parser / postcss** — minificatore JS, parser JS, post-processore CSS. Decine di migliaia di righe di codice minificato che analizzano nuovamente input arbitrari: è qui che emergono forme AST rare.
- **ajv** — validatore di schemi JSON che compila JIT ogni schema in una funzione di validazione personalizzata tramite `new Function(...)`. Mette alla prova il percorso del costruttore Function, su cui fanno affidamento la maggior parte delle librerie di schemi e templating.
- **mobx** — stato reattivo basato su proxy. Ogni lettura di un observable passa attraverso un trap Proxy `get` che registra una dipendenza; ogni scrittura attiva le reazioni. Uno stress test per l'infrastruttura Proxy, le Map e gli array observable, gli oggetti annidati e lo scheduler autorun.
- **cheerio / htmlparser2** — jQuery lato server basato su un parser HTML veloce. Analisi tramite motore dei selettori, attraversamento in stile DOM, manipolazione degli attributi e serializzazione HTML in un unico pacchetto.
- **graphql-js / jsonata** — implementazione di riferimento GraphQL e linguaggio di query JSON. Entrambi fanno ampio uso di schemi, validazione e valutatori ricorsivi: il tipico codice di un «livello dati nel browser».
- **JSZip** — generatore asincrono di archivi ZIP. Gestisce le operazioni tramite pianificazione basata su `setImmediate` e produce veri dati binari, mettendo alla prova sia la superficie dei timer sia i percorsi intensivi in `Uint8Array`.
- **moment / luxon** — calcoli su date e orari. moment è un UMD mutabile, ottimizzato manualmente; luxon è la riscrittura moderna immutabile. Insieme coprono l'intera gamma di formattazione, analisi e calcoli di mesi e anni equivalenti tra fusi orari.
- **mqtt-packet** — codec MQTT JS puro 3.1.1 / 5.0. Impacchettamento e decodifica a livello di byte, oltre a classi di caratteri regex base64 che escludono l'alfabeto, utili per mettere alla prova i casi limite della grammatica Annex-B.
- **xstate / valtio / nanostores / jotai / redux-saga** — una panoramica della moderna gestione dello stato. Macchine a stati, stato proxy, archivi di atomi, atomi derivati, esecutori di effetti basati su generatori: ogni libreria presenta una forma diversa di reattività.
- **escodegen / acorn-walk / estraverse / magic-string** — strumenti per AST. Generazione e attraversamento del codice, modifica non distruttiva del sorgente: i componenti di base di qualsiasi trasformatore JS-su-JS (strumenti di build, codemod, linter).
- **papaparse / lunr / yaml / sax / css-tree** — parser e tokenizer puri. CSV, indice di ricerca full-text, YAML 1.2, parser in streaming in stile SAX XML e AST CSS. Grammatiche diverse, tutte utili per individuare problemi nella scansione a livello di carattere e nel comportamento delle regex.

## Aggiungere altro

Aggiungete una nuova directory sotto `tests/Popular/<name>/` con la struttura a tre file, poi:

```bash
node tests/Popular/gen-oracle.js tests/Popular/<name>   # one-time, generates oracle.txt
git add tests/Popular/<name>
```

La suite PHPUnit la rileva automaticamente alla prossima esecuzione e CI la include perché la modifica interessa `tests/Popular/`.

Ottimi candidati da aggiungere: `chevrotain` (parser combinator, mette alla prova closure e regex), `nanoid` (confine tra crittografia e casualità), `date-fns` (supporto ai fusi orari oltre dayjs).
