
# Popularne pakiety

Zgodność ze specyfikacją nie gwarantuje działania rzeczywistych bibliotek. Silniki JS, które przechodzą 99 % testów test262, wciąż regularnie zawodzą w kodzie produkcyjnym, ponieważ biblioteki zależą od wielu rzadkich „szczegółów specyfikacji” — pułapek Proxy w określonej kolejności, kształtu `Function.prototype.toString`, zachowania wyrażeń regularnych przy trudnych danych wejściowych oraz dokładnego wpływu kolejności `Object.keys` na nazwy obliczanych właściwości.

Phasis weryfikuje **204 szeroko używanych bibliotek** bajt po bajcie względem Node.js (V8). Znajdują się one w repozytorium pod `tests/Popular/`, a CI uruchamia testy przy każdej zmianie kodu źródłowego silnika lub zestawu testów.

## Zakres według kategorii

| Kategoria | Biblioteki |
|---|---|
| **Parsery / 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 |
| **Szablony / 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 |
| **Narzędzia / funkcyjne** | 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 |
| **Dostęp do obiektów** | 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 |
| **Walidacja / schematy** | 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 |
| **Daty / godziny** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Matematyka / liczby** | 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 |
| **Skróty / kryptografia** | 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 |
| **Wyszukiwanie / różnice** | 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 / formaty danych** | 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 |
| **Ciągi / językoznawstwo** | 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 / internet** | 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 |
| **Kompresja / kodowanie / archiwa** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Kolory** | 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 |
| **Klonowanie / równość** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Formatowanie / wyświetlanie** | ms 2.1.3, bytes 3.1.2 |
| **Identyfikatory / UUID** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Rozpoznawanie typów / 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 / konfiguracja** | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| **Pamięć podręczna / wydajność** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asynchroniczność / zdarzenia** | 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 |
| **Stan reaktywny** | 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 / stylizacja** | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| **Budowanie / AST / kompilatory** | 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 (kompilator), typescript 6.0.3 |
| **MQTT / protokół** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Podświetlanie składni** | highlight.js 11.11.1 |
| **Testowanie / asercje** | chai 6.2.1 |

Łącznie: **204 bibliotek** dokładnie odtwarza wynik Node. Wszystkie są przypięte do najnowszego wydania upstream z chwili ostatniej aktualizacji.

## Jak to działa

Każdy scenariusz to katalog `tests/Popular/<lib>/` zawierający trzy pliki:

```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` to test z dostawcą danych PHPUnit, który:

1. Ładuje `lodash.js` + `runner.js` do nowego `new Phasis\Engine()`.
2. Zapisuje wyjście `console.log` w buforze.
3. Sprawdza, czy przechwycony bufor jest bajtowo identyczny z `oracle.txt`.

Ponownie wygeneruj wzorzec za pomocą:

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

(Używane po aktualizacji dołączonej biblioteki — ponownie uruchamia program testowy w rzeczywistym Node i nadpisuje `oracle.txt`.)

## Kontrola CI

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

Uruchamia się przy wypchnięciu zmian i żądaniach pull do `main`, jeśli zmieniono `src/`, `tests/Popular/`, `phpunit.xml.dist`, pliki Composer lub sam workflow, a także przy ręcznym uruchomieniu. Dwa kroki:

1. **Strona Phasis** — uruchamia zestaw testów PHPUnit `popular`, który wykonuje każdą bibliotekę przez Phasis i porównuje wynik z zatwierdzonym wzorcem. Kończy się błędem, jeśli różni się choćby jeden bajt.
2. **Ponowna weryfikacja w Node** — uruchamia `node tests/Popular/gen-oracle.js …` dla każdej biblioteki i sprawdza, czy świeżo wygenerowany wzorzec zgadza się z tym zapisanym w repozytorium. Wykrywa rozbieżności typu „zaktualizowano dołączoną bibliotekę bez aktualizacji wzorca”.

Oba kroki muszą się powieść, zanim PR zostanie scalony. Zmiana w test262, która psuje lodash, jest nie do przyjęcia; podobnie zmiana w lodash, która psuje test262.

## Dlaczego te biblioteki

- **acorn** — parsowanie to najbardziej podatny na błędy obszar każdego silnika JS. Sprawdza każdy przypadek brzegowy składni dodany przez współczesny JS. Jeśli Phasis potrafi analizować dowolny nowoczesny kod za pomocą acorn, środowisko wykonawcze działa poprawnie.
- **mustache.js** — obsługa szablonów to jedno z zastosowań osadzania, które Phasis wyraźnie wspiera (pierwszym konkretnym przykładem w README są „silniki szablonów”). Mustache sprawdza iterację, rozwiązywanie zakresów i przekształcanie ciągów w kolejności stosowanej w rzeczywistych szablonach.
- **lodash** — najczęściej używana biblioteka narzędziowa JS na świecie. Jej ponad 300 funkcji pośrednio wykorzystuje każdą metodę biblioteki standardowej. Jeśli lodash działa, działają też ogólne JS do przekształcania danych.
- **marked** — renderowanie markdown. Praktyczny test, który sprawdza wyrażenia regularne (w dużej liczbie) i manipulowanie ciągami ze stanem między wierszami. Ujawnia rozbieżności między silnikiem wyrażeń regularnych PCRE2 (awaryjnym dla Phasis) a Irregexp używanym przez V8.
- **dayjs** — działania na datach i godzinach często powodują błędy o jeden dzień, których nie wykrywa żaden przypadek test262. dayjs sprawdza różne warianty konstruktora, działania na granicach miesięcy odpowiadających zmianom czasu letniego oraz rozwijanie tokenów formatu w zbliżonych ścieżkach kodu, z których korzysta każda biblioteka dat JS.
- **bignumber.js** — arytmetyka dowolnej precyzji bez TypedArrays sprawdza parsowanie liczb z ciągów, pętle mnożenia i dzielenia dużych liczb całkowitych oraz wybór trybu zaokrąglania — wszystko w czystym JS, więc cały koszt ponosi silnik. Ujawnia subtelne problemy z konwersją Number ↔ String.
- **json5** — liberalne parsowanie JSON w dużej mierze opiera się na wyrażeniach regularnych z klasami znaków i tokenizacji zachowującej stan. To dobry test zarówno poprawności wyrażeń regularnych, jak i granicznych przypadków iteracji po ciągach.
- **fuse.js** — UMD przetranspilowany przez Babel, który sprawdza `_classCallCheck` (wzorzec `this instanceof Ctor` stosowany przez każdą klasę transpilowaną sprzed ES6), a także pełny algorytm rozmytego dopasowywania bitap. Tę postać mają biblioteki transpilowane przez Babel, więc każda usterka w Fuse psuje połowę ekosystemu npm.
- **handlebars** — zaawansowana obsługa szablonów z kompilacją przed renderowaniem. Sprawdza ścieżkę środowiska wykonawczego bez `eval` przez jeden ogromny wpis `compile()`, przechodzenie po AST, wywoływanie helperów za pomocą dynamicznej tabeli wyszukiwania oraz sprawdzanie marki `SafeString` przy użyciu `instanceof` między różnymi realmami. Stanowi kontrast dla prostszego mechanizmu przechodzenia po szablonach w mustache.js.
- **zod** — walidacja schematów w czasie działania. Rozbudowane hierarchie klas (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) z łańcuchami metod zwracającymi uszczegółowione podklasy, formatowanie ustrukturyzowanych błędów, w którym tablica `.issues` po stronie JS musi być bajtowo zgodna z Node, oraz wzorce dyskryminatorów i tagów literałów. Sprawdza kod walidacji intensywnie wykorzystujący programowanie obiektowe, który stanowi warstwę dla połowy współczesnych aplikacji TypeScript.
- **typescript** — *rzeczywisty* kompilator TypeScript działający na osadzonym silniku. Zminifikowany kompilator o rozmiarze 9 MB, który ponownie parsuje dowolny kod TS, przechodzi po AST i generuje JS — najcięższy możliwy ładunek czystego JS. Jeśli Phasis potrafi transpilować typy generyczne, async/await, wyliczenia i hierarchie klas, zachowując zgodność bajt po bajcie z `tsc`, semantyka języka jest poprawna.
- **prettier** — formatter JS narzucający określony styl. Formatowanie kodu JS *z* JS sprawia, że ta sama ścieżka sterowania, która formatuje kod, sprawdza każdy szczegół specyfikacji obsługiwany przez silnik — to wyjątkowo wymagające obciążenie.
- **svelte/compiler** — samodzielny kompilator Svelte. Parsuje kod źródłowy `.svelte`, przechodzi po AST i generuje JS dla celów klienta i SSR.
- **terser / @babel/parser / postcss** — minifikator JS, parser JS, narzędzie do przetwarzania końcowego CSS. Dziesiątki tysięcy wierszy zminifikowanego kodu ponownie parsującego dowolne dane wejściowe — to obszar, w którym pojawiają się rzadkie struktury AST.
- **ajv** — walidator schematów JSON, który kompiluje każde schematy JIT do niestandardowej funkcji walidującej za pomocą `new Function(...)`. Sprawdza ścieżkę konstruktora Function, z której korzysta większość bibliotek schematów i szablonów.
- **mobx** — reaktywny stan oparty na proxy. Każdy odczyt obserwowalnej wartości przechodzi przez pułapkę Proxy `get`, która rejestruje zależność; każdy zapis wywołuje reakcje. To test obciążeniowy infrastruktury Proxy, obserwowalnych map, tablic i zagnieżdżonych obiektów oraz harmonogramu autorun.
- **cheerio / htmlparser2** — jQuery po stronie serwera, oparte na szybkim parserze HTML. Parsowanie selektorów, przechodzenie po strukturze w stylu DOM, modyfikowanie atrybutów i serializacja HTML w jednym pakiecie.
- **graphql-js / jsonata** — implementacja referencyjna GraphQL i język zapytań JSON. Oba rozwiązania intensywnie wykorzystują schematy, walidację i rekurencyjne ewaluatory — typowy kod „warstwy danych w przeglądarce”.
- **JSZip** — asynchroniczne narzędzie do tworzenia archiwów ZIP. Przetwarza zadania według harmonogramu opartego na `setImmediate` i generuje rzeczywiste dane binarne, sprawdzając zarówno warstwę timerów, jak i ścieżki intensywnie wykorzystujące `Uint8Array`.
- **moment / luxon** — działania na datach i godzinach. moment to mutowalny, ręcznie dostrojony UMD; luxon to nowoczesne, niemutowalne przepisanie. Razem obejmują pełen zakres formatowania, parsowania i obliczeń na miesiącach i latach odpowiadających różnym strefom czasowym.
- **mqtt-packet** — czysty JS-owy kodek MQTT 3.1.1 / 5.0. Pakowanie i dekodowanie na poziomie bajtów oraz klasy znaków wyrażeń regularnych dla znaków spoza alfabetu base64, które sprawdzają graniczne przypadki gramatyki Annex-B.
- **xstate / valtio / nanostores / jotai / redux-saga** — przekrój współczesnych rozwiązań do zarządzania stanem. Maszyny stanów, stan oparty na proxy, magazyny atomów, atomy pochodne i generatory uruchamiające efekty — każda biblioteka sprawdza inny model reaktywności.
- **escodegen / acorn-walk / estraverse / magic-string** — narzędzia AST. Generowanie kodu, przechodzenie po strukturze i niedestrukcyjna edycja źródła — podstawowe elementy transformatorów JS na JS (narzędzi budujących, codemodów i linterów).
- **papaparse / lunr / yaml / sax / css-tree** — czyste parsery i tokenizatory. CSV, indeks wyszukiwania pełnotekstowego, YAML 1.2, strumieniowe parsowanie XML w stylu SAX i AST CSS. Różne gramatyki, a każda dobrze sprawdza skanowanie znak po znaku i zachowanie wyrażeń regularnych.

## Dodawanie kolejnych bibliotek

Umieść nowy katalog w `tests/Popular/<name>/`, zachowując strukturę trzech plików, a następnie:

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

Przy następnym uruchomieniu zestaw PHPUnit automatycznie wykryje nowy katalog, a CI uwzględni go, ponieważ zmiana dotyczy `tests/Popular/`.

Warto dodać między innymi: `chevrotain` (kombinator parserów, sprawdza domknięcia i wyrażenia regularne), `nanoid` (granice kryptografii i losowości), `date-fns` (obsługę stref czasowych wykraczającą poza dayjs).
