
# Beliebte Pakete

Die Einhaltung der Spezifikation garantiert nicht, dass echte Bibliotheken funktionieren. JS-Engines, die 99 % von test262 bestehen, scheitern in Produktionscode noch regelmäßig an langen Listen von „Spezialfällen der Spezifikation“ – etwa Proxy-Traps in bestimmter Reihenfolge, `Function.prototype.toString`-Formen, Regex-Verhalten bei kniffligen Eingaben oder der genauen Wechselwirkung zwischen der Reihenfolge von `Object.keys` und berechneten Eigenschaftsnamen.

Phasis prüft **204 weit verbreitete Bibliotheken** bytegenau gegen Node.js (V8). Sie befinden sich im Repo unter `tests/Popular/`; CI führt sie bei jeder Änderung am Engine-Quellcode oder an der Suite aus.

## Abdeckung nach Kategorie

| Kategorie | Bibliotheken |
|---|---|
| **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 |
| **Templating / 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 |
| **Hilfsfunktionen / funktional** | 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 |
| **Objektzugriff** | 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 |
| **Validierung / Schema** | 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 / Uhrzeit** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Mathematik / Zahlen** | 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 / Kryptografie** | 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 |
| **Suche / Unterschiede** | 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 / Datenformate** | 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 |
| **Zeichenfolgen / Linguistik** | 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 |
| **Komprimierung / Kodierung / Archive** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Farben** | 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 |
| **Klonen / Gleichheit** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Format / Anzeige** | ms 2.1.3, bytes 3.1.2 |
| **IDs / UUIDs** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Typ-Erkennung / 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 / Konfiguration** | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| **Caches / Leistung** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asynchronität / Ereignisse** | 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 |
| **Reaktiver Zustand** | 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 / Styling** | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| **Build / AST / Compiler** | 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 / Protokoll** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Syntaxhervorhebung** | highlight.js 11.11.1 |
| **Tests / Assertions** | chai 6.2.1 |

Insgesamt: **204 Bibliotheken** geben exakt dieselbe Ausgabe wie Node aus. Alle sind auf die neueste Upstream-Version beim letzten Aktualisieren festgelegt.

## So funktioniert es

Jedes Szenario ist ein `tests/Popular/<lib>/`-Verzeichnis mit drei Dateien:

```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` ist ein PHPUnit-Test mit Datenprovider, der:

1. `lodash.js` + `runner.js` in ein frisches `new Phasis\Engine()` lädt.
2. Die Ausgabe von `console.log` in einem Puffer erfasst.
3. Prüft, ob der erfasste Puffer bytegenau `oracle.txt` entspricht.

Eine Referenz neu erzeugen mit:

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

(Wird verwendet, wenn du die mitgelieferte Bibliothek aktualisierst – führt den Runner erneut unter echtem Node aus und überschreibt `oracle.txt`.)

## CI-Prüfschranke

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

Wird bei Pushes und Pull Requests an `main` ausgeführt, die `src/`, `tests/Popular/`, `phpunit.xml.dist`, Composer-Dateien oder den Workflow selbst ändern, sowie bei manueller Ausführung. Zwei Schritte:

1. **Phasis-Seite** – führt die PHPUnit-Testsuite `popular` aus. Sie führt jede Bibliothek über Phasis aus und vergleicht die Ausgabe mit der eingecheckten Referenz. Schon ein abweichendes Byte lässt den Schritt fehlschlagen.
2. **Erneute Node-Prüfung** – führt `node tests/Popular/gen-oracle.js …` für jede Bibliothek aus und prüft, ob die neu erzeugte Referenz mit der eingecheckten übereinstimmt. Erkennt Abweichungen, wenn eine mitgelieferte Bibliothek aktualisiert wurde, ohne die Referenz zu aktualisieren.

Beide Schritte müssen erfolgreich sein, bevor der PR zusammengeführt wird. Ein Erfolg bei test262, der lodash beeinträchtigt, ist nicht akzeptabel; ebenso wenig ein Erfolg bei lodash, der test262 beeinträchtigt.

## Warum diese Bibliotheken

- **acorn** — Das Parsen ist die anfälligste Stelle jeder JS-Engine. Es prüft jeden syntaktischen Sonderfall, den modernes JS mitbringt. Wenn Phasis beliebigen modernen Code mit acorn parsen kann, ist die Laufzeitumgebung solide.
- **mustache.js** — Templating zählt zu den Einbettungsfällen, auf die Phasis ausdrücklich ausgelegt ist (das erste konkrete Beispiel in der README sind „templating engines“). Mustache prüft Iteration, Bereichsauflösung und String-Transformationen in der Reihenfolge echter Templates.
- **lodash** — die meistgenutzte JS-Hilfsbibliothek weltweit. Ihre über 300 Funktionen greifen indirekt auf jede Methode der Standardbibliothek zu. Wenn lodash funktioniert, funktioniert auch generisches JS zur Datentransformation.
- **marked** — Markdown-Rendering. Praxisnah und prüft reguläre Ausdrücke (sehr viele) sowie String-Manipulation mit zeilenübergreifendem Zustand. Macht Abweichungen zwischen der Regex-Engine PCRE2 (Fallback von Phasis) und V8s Irregexp sichtbar.
- **dayjs** — Datums- und Zeitberechnungen sind eine klassische Quelle für Fehler um einen Tag, die kein test262-Fall abfängt. dayjs prüft Konstruktionsvarianten, Berechnungen über DST-äquivalente Monatsgrenzen und die Erweiterung von Format-Tokens über ungefähr dieselben Codepfade wie jede JS-Datumsbibliothek.
- **bignumber.js** — Arithmetik mit beliebiger Genauigkeit ohne TypedArrays prüft stringbasiertes Zahlenparsing, Schleifen für Multiplikation und Division großer Ganzzahlen sowie die Auswahl des Rundungsmodus — alles in reinem JS, sodass die Engine die gesamte Arbeit übernimmt. Macht subtile Fehler bei der Umwandlung zwischen Number und String sichtbar.
- **json5** — Das tolerante JSON-Parsing stützt sich stark auf Zeichenklassen in regulären Ausdrücken und zustandsbehaftete Tokenisierung. Ein guter Frühindikator für korrekte reguläre Ausdrücke und die Grenzfälle der String-Iteration.
- **fuse.js** — ein mit Babel transpiliertes UMD, das `_classCallCheck` prüft (das `this instanceof Ctor`-Muster, das jede vor ES6 transpilierten Klasse verwendet) sowie den vollständigen Bitap-Algorithmus für unscharfe Treffer. Diese Form teilen alle mit Babel transpilierten Bibliotheken; alles, was Fuse kaputt macht, betrifft also die halbe npm-Landschaft.
- **handlebars** — leistungsfähiges Templating mit Kompilieren vor dem Rendern. Prüft den Laufzeitpfad ohne `eval` über einen einzigen riesigen `compile()`-Eintrag, AST-Traversierung, Helper-Aufrufe über eine dynamische Nachschlagetabelle und `SafeString`-Markenprüfung mit `instanceof` über verschiedene Realms hinweg. Ein Gegenstück zum einfacheren Template-Walker von mustache.js.
- **zod** — Schema-Validierung zur Laufzeit. Tiefe Klassenhierarchien (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) mit Methodenverkettung, die verfeinerte Unterklassen zurückgibt, strukturierte Fehlerformatierung, bei der die Form des JS-seitigen `.issues`-Arrays bytegenau mit Node übereinstimmen muss, sowie Discriminator- und Literal-Tag-Muster. Prüft den objektorientierten Validierungscode, der die Hälfte moderner TypeScript-Apps umhüllt.
- **typescript** — der *echte* TypeScript-Compiler auf der eingebetteten Engine. Ein 9 MB großer minimierter Compiler, der beliebiges TS erneut parst, den AST durchläuft und JS ausgibt — die schwerste vorstellbare reine JS-Ladung. Wenn Phasis Generics, async/await, Enums und Klassenhierarchien bytegenau wie `tsc` transpiliert, stimmt die Sprachsemantik.
- **prettier** — ein meinungsstarker JS-Formatter. JS *mit* JS zu formatieren bedeutet, dass dieselben Kontrollflüsse, die deinen Code formatieren, jede Spezifikationsecke der Engine berühren — eine besonders anspruchsvolle Belastung.
- **svelte/compiler** — der eigenständige Compiler von Svelte. Er parst `.svelte`-Quellcode, durchläuft den AST und gibt JS sowohl für Client- als auch SSR-Ziele aus.
- **terser / @babel/parser / postcss** — JS-Minifizierer, JS-Parser und CSS-Nachbearbeitung. Zehntausende Zeilen minimierten Codes, die beliebige Eingaben erneut parsen — hier zeigen sich seltene AST-Formen.
- **ajv** — JSON-Schema-Validator, der jedes Schema über `new Function(...)` JIT in eine eigene Validatorfunktion kompiliert. Prüft den Function-Konstruktorpfad, auf den sich die meisten Schema- und Templating-Bibliotheken stützen.
- **mobx** — reaktiver Zustand auf Proxy-Basis. Jeder Lesezugriff auf ein Observable läuft durch einen Proxy-`get`-Trap, der eine Abhängigkeit registriert; jeder Schreibzugriff löst Reaktionen aus. Ein Stresstest für die Proxy-Infrastruktur, Observable Maps, Arrays und verschachtelte Objekte sowie den autorun-Scheduler.
- **cheerio / htmlparser2** — jQuery auf der Serverseite, auf Basis eines schnellen HTML-Parsers. Parser der Selektor-Engine, DOM-artige Traversierung, Attributmanipulation und HTML-Serialisierung in einem Paket.
- **graphql-js / jsonata** — Referenzimplementierung von GraphQL und Abfragesprache JSON. Beide setzen stark auf Schemas, Validierung und rekursive Auswerter — typische „Datenschicht im Browser“-Programme.
- **JSZip** — asynchroner ZIP-Archiversteller. Steuert die Arbeit über `setImmediate`-gestützte Planung und erzeugt echte Binärausgabe; damit werden sowohl die Timer-Schnittstelle als auch Pfade mit vielen `Uint8Array` geprüft.
- **moment / luxon** — Datums- und Zeitberechnungen. moment ist ein veränderliches, handoptimiertes UMD; luxon die moderne unveränderliche Neufassung. Zusammen decken sie Formatierung, Parsing und Monats- und Jahresberechnungen über äquivalente Zeitzonen hinweg ab.
- **mqtt-packet** — reiner JS-Codec für MQTT 3.1.1 / 5.0. Packen und Dekodieren auf Byte-Ebene sowie Zeichenklassen für reguläre Ausdrücke, die nicht zum Base64-Alphabet gehörende Zeichen erkennen und Randfälle der Annex-B-Grammatik prüfen.
- **xstate / valtio / nanostores / jotai / redux-saga** — die moderne Bandbreite der Zustandsverwaltung. Zustandsmaschinen, Proxy-Zustand, Atom-Stores, abgeleitete Atome und Generator-basierte Effekt-Runner — jede Bibliothek prüft eine andere Form von Reaktivität.
- **escodegen / acorn-walk / estraverse / magic-string** — AST-Werkzeuge. Codegenerierung, Traversierung und nichtdestruktive Quelltextbearbeitung — die Bausteine für alle JS-zu-JS-Transformatoren (Build-Tools, Codemods, Linter).
- **papaparse / lunr / yaml / sax / css-tree** — reine Parser und Tokenizer. CSV, Volltext-Suchindex, YAML 1.2, Streaming-XML im SAX-Stil und CSS-AST. Unterschiedliche Grammatiken, alle gute Frühindikatoren für zeichenweises Scannen und das Verhalten regulärer Ausdrücke.

## Weitere hinzufügen

Lege unter `tests/Popular/<name>/` ein neues Verzeichnis mit der Struktur aus drei Dateien an und führe dann Folgendes aus:

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

Die PHPUnit-Testsuite erkennt es beim nächsten Lauf automatisch, und CI nimmt es auf, weil die Änderung `tests/Popular/` betrifft.

Gute Kandidaten für Ergänzungen: `chevrotain` (Parser-Kombinator, prüft Closures und reguläre Ausdrücke), `nanoid` (Grenzbereich von Kryptografie und Zufallszahlen), `date-fns` (Zeitzonenfunktionen über dayjs hinaus).
