
# Priljubljeni paketi

Skladnost s specifikacijo ne zagotavlja delovanja resničnih knjižnic. Pogoni JS, ki opravijo 99 % testov test262, se še vedno redno zaletijo v težave s produkcijsko kodo, ker so knjižnice odvisne od številnih »robnih primerov« v specifikaciji — pasti Proxy v določenem vrstnem redu, oblika `Function.prototype.toString`, vedenje regularnih izrazov pri zahtevnih vhodnih podatkih in natančen način, kako vrstni red `Object.keys` vpliva na izračunana imena lastnosti.

Phasis preverja **204 pogosto uporabljenih knjižnic** bajt za bajtom glede na Node.js (V8). V repozitoriju so v mapi `tests/Popular/`; CI jih zažene ob vsaki spremembi izvorne kode pogona ali zbirke testov.

## Pokritost po kategorijah

| Kategorija | Knjižnice |
|---|---|
| **Razčlenjevalniki / 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 |
| **Predloge / 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 |
| **Pripomočki / funkcionalno** | 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 |
| **Dostop do objektov** | 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 |
| **Preverjanje / sheme** | 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 |
| **Datum / čas** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Matematika / števila** | 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 |
| **Zgoščevanje / kriptografija** | 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 |
| **Iskanje / razlike** | 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 / podatkovni formati** | 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 |
| **Nizi / jezikoslovje** | 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 / splet** | 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 |
| **Stiskanje / kodiranje / arhivi** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Barve** | 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 |
| **Kloniranje / enakost** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Oblika / prikaz** | ms 2.1.3, bytes 3.1.2 |
| **ID-ji / UUID-ji** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Zaznavanje tipov / 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 / konfiguracija** | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| **Predpomnilniki / zmogljivost** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asinhronost / dogodki** | 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 |
| **Reaktivno stanje** | 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 / oblikovanje** | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| **Gradnja / AST / prevajalniki** | 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 (prevajalnik), typescript 6.0.3 |
| **MQTT / protokol** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Označevanje sintakse** | highlight.js 11.11.1 |
| **Testiranje / preverjanje trditev** | chai 6.2.1 |

Skupaj: **204 knjižnic** natančno ponovi izhod Node. Vse so pripete na najnovejšo izdajo izvornega projekta ob zadnji posodobitvi.

## Kako deluje

Vsak scenarij je imenik `tests/Popular/<lib>/` s tremi datotekami:

```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` je test s ponudnikom podatkov PHPUnit, ki:

1. Naloži `lodash.js` + `runner.js` v svež `new Phasis\Engine()`.
2. Zajame izhod `console.log` v medpomnilnik.
3. Preveri, ali je zajeti medpomnilnik po bajtih enak `oracle.txt`.

Znova ustvari referenčni rezultat z ukazom:

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

(Uporabi se pri posodobitvi vključene knjižnice — ponovno zažene izvajalnik v pravem Node in prepiše `oracle.txt`.)

## Preverjanje CI

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

Zažene se ob potiskih in zahtevah za združitev v `main`, ki spremenijo `src/`, `tests/Popular/`, `phpunit.xml.dist`, datoteke Composer ali sam delovni tok, ter ob ročnem zagonu. Dva koraka:

1. **Stran Phasis** — zažene testno zbirko PHPUnit `popular`, ki vsako knjižnico izvede prek Phasis in primerja z zabeleženim referenčnim rezultatom. Ne uspe, če se razlikuje že en sam bajt.
2. **Ponovno preverjanje Node** — zažene `node tests/Popular/gen-oracle.js …` za vsako knjižnico in preveri, ali se na novo ustvarjeni referenčni rezultat ujema z različico v shrambi. Zazna razhajanje »vključena knjižnica je bila posodobljena brez posodobitve referenčnega rezultata«.

Pred združitvijo PR morata uspeti oba koraka. Zmaga test262, ki pokvari lodash, ni sprejemljiva; prav tako ni sprejemljiva zmaga za lodash, ki pokvari test262.

## Zakaj te knjižnice

- **acorn** — razčlenjevanje je najobčutljivejši del vsakega mehanizma JS. Preizkusi vse skrajne sintaktične primere, ki jih prinaša sodobni JS. Če lahko Phasis z acorn razčleni poljubno sodobno kodo, je izvajalno okolje zanesljivo.
- **mustache.js** — predloge so eden od primerov uporabe vdelave, ki jih Phasis izrecno podpira (prvi konkreten primer v README so »mehanizmi za predloge«). Mustache preverja iteracijo, razreševanje obsegov in pretvorbe nizov v zaporedju, značilnem za prave predloge.
- **lodash** — najpogosteje uporabljena knjižnica pripomočkov JS na svetu. Njenih več kot 300 funkcij posredno uporabi vse metode standardne knjižnice. Če deluje lodash, deluje tudi splošni JS za pretvorbo podatkov.
- **marked** — izrisovanje Markdowna. Je praktičen in preizkuša regularne izraze (veliko njih) ter obdelavo nizov s stanjem prek več vrstic. Razkrije razhajanja med mehanizmom regularnih izrazov PCRE2 (rezervna možnost za Phasis) in Irregexp v V8.
- **dayjs** — računanje z datumom in časom je klasičen vir napak za eno enoto, ki jih ne odkrije noben primer test262. dayjs pokriva različice konstruktorjev, računanje čez meje mesecev, enakovredne prehodu na poletni čas, ter razširjanje žetonov za oblikovanje v približno enakih poteh kode, kot jih uporablja vsaka knjižnica za datum v JS.
- **bignumber.js** — aritmetika poljubne natančnosti brez TypedArrays preverja razčlenjevanje števil iz nizov, zanke za množenje in deljenje velikih celih števil ter izbiro načina zaokroževanja — vse v čistem JS, zato celoten strošek nosi mehanizem. Razkrije vsako subtilno napako pri pretvorbi števila ↔ niza.
- **json5** — sproščeno razčlenjevanje JSON se močno opira na regularne izraze z razredi znakov in tokenizacijo s stanjem. Dober zgodnji pokazatelj pravilnosti regularnih izrazov in robnih primerov pri iteraciji po nizih.
- **fuse.js** — UMD, preveden z Babelom, ki preizkuša `_classCallCheck` (vzorec `this instanceof Ctor`, ki ga uporablja vsak razred, preveden pred ES6) ter celoten algoritem za približno iskanje Bitap. Takšno obliko ima vsaka knjižnica, prevedena z Babelom, zato vse, kar pokvari Fuse, prizadene polovico ekosistema npm.
- **handlebars** — zmogljive predloge s prevajanjem in nato izrisom. Preizkuša izvajalno pot brez `eval` prek ene same ogromne vstopne točke `compile()`, prehod skozi AST, klice pomočnikov prek dinamične iskalne tabele in preverjanje oznake znamke `SafeString`, ki uporablja `instanceof` med okolji. Dopolnjuje preprostejši sprehajalnik predlog za mustache.js.
- **zod** — preverjanje shem med izvajanjem. Obsežne hierarhije razredov (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) z veriženjem metod, ki vračajo podrazrede z dodatnimi omejitvami, strukturirano oblikovanje napak, pri katerem se mora oblika polja `.issues` na strani JS bajt za bajtom ujemati z Node, ter vzorci diskriminatorjev in literalnih oznak. Preizkuša objektno usmerjeno validacijsko kodo, ki obdaja polovico sodobnih aplikacij TypeScript.
- **typescript** — *dejanski* prevajalnik TypeScript, ki deluje v vdelanem mehanizmu. Minificiran prevajalnik velikosti 9 MB, ki znova razčleni poljuben TS, prehodi AST in odda JS — najtežjo predstavljivo čisto obremenitev JS. Če lahko Phasis prevede generike, async/await, enumeracije in hierarhije razredov tako, da so po bajtih enaki `tsc`, je semantika jezika zanesljiva.
- **prettier** — oblikovalnik JS z izrazitim mnenjem. Oblikovanje JS *z* JS pomeni, da isti tok izvajanja, ki oblikuje vašo kodo, doseže vsak robni primer specifikacije mehanizma — to je izjemno zahtevna obremenitev.
- **svelte/compiler** — samostojni prevajalnik Svelte. Razčleni izvorno kodo `.svelte`, prehodi AST in odda JS za cilja odjemalca in SSR.
- **terser / @babel/parser / postcss** — minifikator JS, razčlenjevalnik JS, procesor po obdelavi CSS. Več deset tisoč vrstic minificirane kode, ki znova razčlenjuje poljuben vhod — prav tu se pojavijo redke oblike AST.
- **ajv** — preverjevalnik shem JSON, ki vsako shemo JIT prevede v funkcijo po meri prek `new Function(...)`. Preizkuša pot konstruktorja Function, na katero se opira večina knjižnic za sheme in predloge.
- **mobx** — reaktivno stanje na podlagi proxyjev. Vsak bralni dostop do opazljive vrednosti poteka skozi past Proxy `get`, ki registrira odvisnost; vsak zapis sproži odzive. Preizkus obremenitve infrastrukture Proxy ter opazljivih map, polj, ugnezdenih objektov in razporejevalnika autorun.
- **cheerio / htmlparser2** — jQuery na strežniški strani, zgrajen na hitrem razčlenjevalniku HTML. Razčlenjevanje z izbirnim mehanizmom, prehajanje po vzoru DOM, spreminjanje atributov in serializacija HTML v enem paketu.
- **graphql-js / jsonata** — referenčna izvedba GraphQL in poizvedovalni jezik JSON. Oba se močno opirata na sheme, preverjanje in rekurzivne vrednotilnike — značilno kodo za »podatkovno plast v brskalniku«.
- **JSZip** — asinhroni graditelj arhivov ZIP. Delo razporeja prek razporejanja na podlagi `setImmediate` in ustvarja pravi binarni izhod, s čimer preizkuša tako časovno površino kot poti, ki se močno opirajo na `Uint8Array`.
- **moment / luxon** — računanje z datumom in časom. moment je spremenljiv, ročno optimiziran UMD; luxon je sodobna nespremenljiva predelana različica. Skupaj pokrivata celoten obseg oblikovanja, razčlenjevanja ter računanja z meseci in leti, enakovrednimi po časovnem pasu.
- **mqtt-packet** — čisti JS MQTT 3.1.1 / kodek 5.0. Pakiranje in dekodiranje na ravni bajtov ter razredi znakov regularnih izrazov za znake izven abecede base64, ki preizkušajo robne primere slovnice Annex-B.
- **xstate / valtio / nanostores / jotai / redux-saga** — nabor sodobnih pristopov za upravljanje stanja. Končni avtomati, stanje proxyjev, shrambe atomov, izpeljani atomi in izvajalniki učinkov na podlagi generatorjev — vsaka knjižnica preizkuša drugačno obliko reaktivnosti.
- **escodegen / acorn-walk / estraverse / magic-string** — orodja za AST. Generiranje kode, prehajanje in nedestruktivno urejanje izvorne kode — gradniki vsakega pretvornika JS v JS (orodja za gradnjo, codemodi, linterji).
- **papaparse / lunr / yaml / sax / css-tree** — čisti razčlenjevalniki in tokenizatorji. CSV, indeks za iskanje po celotnem besedilu, YAML 1.2, pretočni XML v slogu SAX in AST CSS. Različne slovnice, vse pa so dobri zgodnji pokazatelji za skeniranje na ravni znakov in vedenje regularnih izrazov.

## Dodajanje novih

Dodajte nov imenik pod `tests/Popular/<name>/` v obliki s tremi datotekami, nato:

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

Zbirka PHPUnit ga samodejno odkrije pri naslednjem zagonu, CI pa ga vključi, ker sprememba zadeva `tests/Popular/`.

Dobre možnosti za dodajanje: `chevrotain` (kombinator razčlenjevalnikov, preizkuša zaprtja + regularne izraze), `nanoid` (meja kriptografije in naključnosti), `date-fns` (podpora časovnim pasovom poleg dayjs).
