
# Suositut paketit

Spesifikaationmukaisuus ei takaa, että oikeat kirjastot toimivat. Moottorit JS, jotka läpäisevät 99 % test262-testeistä, rikkoutuvat silti toistuvasti tuotantokoodissa, koska kirjastot ovat riippuvaisia pitkästä hännästä spesifikaation reunatapauksia — esimerkiksi Proxy-ansoista tietyssä järjestyksessä, `Function.prototype.toString`-rakenteesta, säännöllisten lausekkeiden toiminnasta hankalilla syötteillä sekä täsmällisestä tavasta, jolla `Object.keys`-järjestys vaikuttaa laskettuihin ominaisuuksien nimiin.

Phasis varmistaa **204 laajalti käytetyn kirjaston** tulokset tavuntarkasti vertaamalla niitä Node.js:n tuloksiin (V8). Kirjastot ovat repossa hakemistossa `tests/Popular/`, ja CI suorittaa testit aina, kun moottorin lähdekoodia tai testisarjaa muutetaan.

## Kattavuus luokittain

| Luokka | Kirjastot |
|---|---|
| **Jäsentimet / 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 |
| **Mallipohjat / 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 |
| **Apuohjelmat / funktionaalinen** | 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 |
| **Objektien käyttö** | 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 |
| **Validointi / skeema** | 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 |
| **Päivämäärä / aika** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Matematiikka / luvut** | 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 |
| **Hajautus / salaus** | 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 |
| **Haku / erotusten vertailu** | 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 / tiedostomuodot** | 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 |
| **Merkkijonot / kieli** | 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 / verkko** | 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 |
| **Pakkaus / koodaus / arkistot** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Värit** | 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 |
| **Kloonaus / yhtäsuuruus** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Muotoilu / näyttö** | ms 2.1.3, bytes 3.1.2 |
| **Tunnisteet / UUID:t** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Tyyppien tunnistus / glob-kuviot** | 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 / asetukset** | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| **Välimuistit / suorituskyky** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asynkronisuus / tapahtumat** | 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 |
| **Reaktiivinen tila** | 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 / tyylit** | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| **Koonti / AST / kääntäjät** | 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 (kääntäjä), typescript 6.0.3 |
| **MQTT / protokolla** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Syntaksin korostus** | highlight.js 11.11.1 |
| **Testaus / väitteet** | chai 6.2.1 |

Yhteensä: **204 kirjastoa** tuottaa tarkalleen Nodea vastaavan tulosteen. Kaikkien kirjastojen versiot on lukittu viimeisimmän päivityksen aikaan saatavilla olleisiin uusimpiin upstream-julkaisuihin.

## Näin se toimii

Jokainen skenaario on `tests/Popular/<lib>/`-hakemisto, jossa on kolme tiedostoa:

```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` on PHPUnit-testi, joka käyttää data-provideria ja:

1. Lataa `lodash.js`n ja `runner.js`n uuteen `new Phasis\Engine()`een.
2. Tallentaa `console.log`-tulosteen puskuriin.
3. Varmistaa, että tallennettu puskuri on tavuntarkasti sama kuin `oracle.txt`.

Luo vertailutulos uudelleen komennolla:

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

(Käytetään vendoroidun kirjaston päivityksen yhteydessä: suorittaa ajurin uudelleen aidolla Node-ympäristöllä ja korvaa `oracle.txt`n.)

## CI-porttiehto

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

Käynnistyy pushien ja pull requestien yhteydessä haaraan `main`, kun niissä muutetaan tiedostoja `src/`, `tests/Popular/` tai `phpunit.xml.dist`, Composer-tiedostoja tai itse työnkulkua, sekä manuaalisesti käynnistettäessä. Kaksi vaihetta:

1. **Phasis-puoli** — suorittaa testisarjan PHPUnit `popular`, joka ajaa jokaisen kirjaston Phasisn kautta ja vertaa tulosta tallennettuun vertailutulokseen. Epäonnistuu, jos yksikin tavu poikkeaa.
2. **Node-uudelleenvarmistus** — suorittaa kunkin kirjaston `node tests/Popular/gen-oracle.js …`n ja varmistaa, että juuri luotu vertailutulos vastaa versionhallintaan tallennettua. Havaitsee eron, jos vendoroitua kirjastoa on päivitetty vertailutulosta päivittämättä.

Molempien on onnistuttava ennen PR:n yhdistämistä. test262:n läpäiseminen ei kelpaa, jos lodash rikkoutuu; eikä lodashin toimivuus kelpaa, jos test262 rikkoutuu.

## Miksi nämä kirjastot

- **acorn** — jäsennys on minkä tahansa JS-moottorin herkin osa. Se käy läpi kaikki syntaktiset erikoistapaukset, joita moderni JS tuo mukanaan. Jos Phasis pystyy jäsentämään mielivaltaista modernia koodia acornilla, ajonaikainen ympäristö toimii oikein.
- **mustache.js** — mallipohjien käsittely on yksi upotuskäyttötapauksista, joihin Phasis nimenomaisesti tähtää (README:n ensimmäinen konkreettinen esimerkki on "mallipohjamoottorit"). Mustache testaa iteraatiota, näkyvyysalueen ratkaisua ja merkkijonomuunnoksia siinä järjestyksessä kuin oikeat mallipohjat niitä käyttävät.
- **lodash** — maailman käytetyin JS-apuohjelmakirjasto. Sen yli 300 toimintoa koskettavat välillisesti kaikkia vakiokirjaston metodeja. Jos lodash toimii, yleiset datamuunnosten JS toimivat.
- **marked** — Markdown-renderöintiä. Käytännöllinen testi, joka koettelee säännöllisiä lausekkeita (paljon) sekä rivinvaihtoja ylittävää tilallista merkkijonojen käsittelyä. Tuo esiin säännöllisten lausekkeiden moottorien erot PCRE2:n (Phasis:n vararatkaisu) ja V8:n Irregexpiin välillä.
- **dayjs** — päivämäärä- ja aikalaskenta aiheuttaa usein yhden yksikön virheitä, joita mikään test262-tapaus ei löydä. dayjs testaa konstruktorin eri muunnelmia, laskentaa DST:tä vastaavien kuukauden rajojen yli sekä muotoilumerkkien laajennusta pitkälti samoilla koodipoluilla kuin jokainen JS-päivämääräkirjasto.
- **bignumber.js** — mielivaltaisen tarkkuuden laskenta ilman TypedArrays-rakenteita testaa merkkijonopohjaista lukujen jäsennystä, suurten kokonaislukujen kertomis- ja jakosilmukoita sekä pyöristystavan valintaa. Kaikki tehdään puhtaalla JS:llä, joten moottori kantaa koko kuorman. Paljastaa kaikki hienovaraisetkin virheet Number- ja String-muunnoksissa.
- **json5** — rennomman JSON-jäsennyksen toiminta nojaa vahvasti merkkiluokkien säännöllisiin lausekkeisiin ja tilalliseen tokenisointiin. Hyvä koetinkivi sekä säännöllisten lausekkeiden oikeellisuudelle että merkkijonojen iteroinnin rajatapauksille.
- **fuse.js** — Babelin transpiloima UMD, joka testaa `_classCallCheck`-ominaisuutta (`this instanceof Ctor`-mallia, jota kaikki ES6:ta edeltävät transpiloidut luokat käyttävät) sekä koko Bitap-sumeahakualgoritmia. Tämä vastaa muodoltaan kaikkia Babelilla transpiloituja kirjastoja, joten mikä tahansa npm-ekosysteemin rikkova ongelma rikkoo myös Fusen.
- **handlebars** — monipuolinen mallipohjamoottori, jossa kääntäminen ja renderöinti ovat erillisiä vaiheita. Testaa `eval`-vapaan ajonaikaisen polun yhden valtavan `compile()`-syötteen läpi, AST:n läpikäyntiä, aputoimintojen valintaa dynaamisen hakutaulukon avulla sekä `SafeString`-tyyppitarkistusta, jossa `instanceof` toimii eri realmien välillä. Vertailukohta mustache.js:n yksinkertaisemmalle mallipohjien läpikävijälle.
- **zod** — ajonaikainen skeeman validointi. Raskaita luokkahierarkioita (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) ja metodiketjutusta, joka palauttaa tarkennettuja aliluokkia; jäsenneltyä virhemuotoilua, jossa JS-puolen `.issues`-taulukon rakenteen on vastattava Nodea tavutasolla, sekä erottimen ja literaalitunnisteen malleja. Testaa olio-ohjelmointia raskaasti käyttävää validointikoodia, jota puolet moderneista TypeScript-sovelluksista käärii ympärilleen.
- **typescript** — *varsinainen* TypeScript-kääntäjä upotetussa moottorissa. 9 MB minimoitua kääntäjää, joka jäsentää uudelleen mielivaltaista TS-koodia, käy AST:n läpi ja tuottaa JS-koodia — raskaimman kuviteltavissa olevan puhtaan JS-kuorman. Jos Phasis pystyy transpiloimaan geneeriset tyypit, async/await-rakenteet, enumit ja luokkahierarkiat tavutasolla yhtäpitävästi `tsc`:n kanssa, kielen semantiikka toimii oikein.
- **prettier** — vahvasti mielipiteellinen JS-muotoilija. Kun JS:ää muotoillaan yhdessä JS:n kanssa, moottorin jokainen määrityksen erikoistapaus kulkee saman ohjauspolun kautta kuin koodisi muotoilu — poikkeuksellisen vaativa kuorma.
- **svelte/compiler** — Svelte:n itsenäinen kääntäjä. Jäsentää `.svelte`-lähdekoodia, käy AST:n läpi ja tuottaa JS-koodia sekä asiakaspuolen että SSR-kohteisiin.
- **terser / @babel/parser / postcss** — JS-minimoija, JS-jäsennin, CSS-jälkikäsittelijä. Kymmeniä tuhansia rivejä minimoitua koodia, joka jäsentää mielivaltaisia syötteitä uudelleen — pinta-ala, jolla harvinaiset AST-rakenteet tulevat esiin.
- **ajv** — JSON-skeemavalidaattori, joka kääntää JIT-tekniikalla jokaisen skeeman omaksi validaattorifunktiokseen `new Function(...)`n avulla. Testaa Function-konstruktoripolkua, johon useimmat skeema- ja mallikirjastot tukeutuvat.
- **mobx** — proksyihin perustuva reaktiivinen tila. Jokainen havaittavan arvon lukeminen kulkee Proxy-`get`-ansa läpi ja rekisteröi riippuvuuden; jokainen kirjoitus käynnistää reaktiot. Rasitustesti Proxy-infrastruktuurille, havaittaville Map-arvoille, taulukoille ja sisäkkäisille olioille sekä autorun-ajastimelle.
- **cheerio / htmlparser2** — palvelinpuolen jQuery nopean HTML-jäsentimen päällä. Valitsinkielen jäsentäminen, DOM-tyylinen läpikäynti, attribuuttien käsittely ja HTML-serialisointi yhdessä paketissa.
- **graphql-js / jsonata** — GraphQLn viitetoteutus ja JSON-kyselykieli. Molemmat hyödyntävät paljon skeemoja, validointia ja rekursiivisia evaluoijia — tyypillistä ”selaimen datakerros” -koodia.
- **JSZip** — asynkroninen ZIP-arkiston rakentaja. Ohjaa työt `setImmediate`-pohjaisen ajoituksen kautta ja tuottaa oikeaa binääritulostetta, joten se testaa sekä ajastinpintaa että `Uint8Array`-painotteisia polkuja.
- **moment / luxon** — päivämäärä- ja aikalaskenta. moment on muuntuva, käsin viritetty UMD; luxon on moderni, muuttumaton uudelleenkirjoitus. Yhdessä ne kattavat muotoilun, jäsentämisen ja aikavyöhykkeistä riippumattoman kuukausi- ja vuosilaskennan.
- **mqtt-packet** — puhtaasti JS-pohjainen MQTT 3.1.1 / 5.0 -koodekki. Tavutason pakkaus ja purku sekä base64-aakkostoon kuulumattomien merkkien säännöllisten lausekkeiden luokat, jotka testaavat Annex-B-kieliopin reunoja.
- **xstate / valtio / nanostores / jotai / redux-saga** — modernin tilanhallinnan kirjo. Tilakoneet, proksytila, atomivarastot, johdetut atomit ja generaattoripohjaiset efektien suorittajat — jokainen kirjasto testaa reaktiivisuutta eri tavoin.
- **escodegen / acorn-walk / estraverse / magic-string** — AST-työkalut. Koodin generointi, läpikäynti ja lähdekoodin tuhoamaton muokkaus — rakennuspalikoita mille tahansa JS-on-JS-muuntimelle (koontityökalut, koodimuunnokset ja linterit).
- **papaparse / lunr / yaml / sax / css-tree** — puhtaita jäsentimiä ja tokenisoijia. CSV, kokotekstihakemisto, YAML 1.2, SAX-tyylinen virtaava XML ja CSS-AST. Eri kielioppeja, jotka kaikki paljastavat hyvin merkkitason skannauksen ja säännöllisten lausekkeiden toiminnan ongelmat.

## Lisääminen

Luo uusi hakemisto kohteen `tests/Popular/<name>/` alle kolmen tiedoston rakenteella ja suorita sitten:

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

PHPUnit-testikokoelma löytää sen automaattisesti seuraavalla suorituskerralla, ja CI ottaa sen mukaan, koska muutos koskee kohdetta `tests/Popular/`.

Hyviä lisäysehdokkaita: `chevrotain` (parserikombinaattori, testaa sulkeumia ja säännöllisiä lausekkeita), `nanoid` (kryptografian ja satunnaisuuden rajapinta), `date-fns` (aikavyöhykeominaisuudet dayjsiä laajemmin).
