
# Populære pakker

Overensstemmelse med specifikationen garanterer ikke, at virkelige biblioteker virker. JS-motorer, der består 99 % af test262, går stadig ofte i stykker med produktionskode, fordi biblioteker afhænger af en lang række "specifikationshjørner" — Proxy-fælder i en bestemt rækkefølge, formen på `Function.prototype.toString`, regex-adfærd med vanskelige input og den præcise måde, som rækkefølgen af `Object.keys` påvirker beregnede egenskabsnavne.

Phasis verificerer **204 udbredte biblioteker** byte for byte mod Node.js (V8). De ligger under `tests/Popular/` i repoet, og CI kører dem, hver gang motorkilden eller testsuiten ændres.

## Dækning efter kategori

| Kategori | Biblioteker |
|---|---|
| **Parsers / 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 |
| **Hjælpeværktøjer / funktionelt** | 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 |
| **Objektadgang** | 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 |
| **Validering / skema** | 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 |
| **Dato / tid** | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| **Matematik / tal** | 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 / kryptografi** | 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 |
| **Søgning / diff** | 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 / dataformater** | 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 |
| **Strenge / lingvistik** | 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 |
| **Komprimering / kodning / arkiv** | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| **Farver** | 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 |
| **Kloning / lighed** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Format / visning** | ms 2.1.3, bytes 3.1.2 |
| **ID'er / UUID'er** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Typegenkendelse / 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 / ydeevne** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Async / hændelser** | 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 |
| **Reaktiv tilstand** | 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 / compilere** | 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 / protokol** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Syntaksfremhævning** | highlight.js 11.11.1 |
| **Test / påstande** | chai 6.2.1 |

I alt: **204 biblioteker** gengiver alle Nodes output præcist. Alle er låst til den seneste upstream-udgivelse fra den seneste opdatering.

## Sådan fungerer det

Hvert scenarie er en `tests/Popular/<lib>/`-mappe med tre filer:

```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` er en PHPUnit-test med dataleverandør, der:

1. Indlæser `lodash.js` + `runner.js` i en ny `new Phasis\Engine()`.
2. Registrerer `console.log`-output i en buffer.
3. Kontrollerer, at den registrerede buffer er byte for byte identisk med `oracle.txt`.

Gendan en oracle med:

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

(Bruges, når du opdaterer det medfølgende bibliotek — kører runneren igen under rigtig Node og overskriver `oracle.txt`.)

## CI-kontrol

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

Kører ved pushes og pull requests til `main`, der ændrer `src/`, `tests/Popular/`, `phpunit.xml.dist`, filerne Composer eller selve workflowet, samt ved manuel start. To trin:

1. **Phasis-siden** — kører test262-testsuiten PHPUnit `popular`, som kører hvert bibliotek gennem Phasis og sammenligner med den indtjekkede oracle. Fejler, hvis en enkelt byte afviger.
2. **Node-genverificering** — kører `node tests/Popular/gen-oracle.js …` mod hvert bibliotek og kontrollerer, at den nyligt genererede oracle stemmer overens med den indtjekkede. Opdager afvigelser, hvor et medfølgende bibliotek blev opdateret uden at opdatere oracle.

Begge skal bestå, før PR'en flettes. En forbedring i test262, der ødelægger lodash, kan ikke accepteres; det kan en forbedring i lodash, der ødelægger test262, heller ikke.

## Hvorfor disse biblioteker

- **acorn** — parsing er det mest skrøbelige område i enhver JS-motor. Det afprøver alle de syntaktiske særtilfælde, som moderne JS tilføjer. Hvis Phasis kan parse vilkårlig moderne kode med acorn, er kørselsmiljøet solidt.
- **mustache.js** — skabelonbehandling er en af de indlejringsopgaver, Phasis udtrykkeligt retter sig mod (det første konkrete eksempel i README er "skabelonmotorer"). Mustache afprøver iteration, navneopslag i scopes og strengtransformationer i samme rækkefølge som rigtige skabeloner.
- **lodash** — det mest anvendte JS-hjælpebibliotek i verden. Dets 300+ funktioner berører indirekte alle metoder i standardbiblioteket. Hvis lodash virker, virker generel datatransformation i JS.
- **marked** — rendering af markdown. En praktisk opgave, der afprøver mange regulære udtryk samt strengbehandling med tilstand på tværs af linjer. Afslører forskelle mellem regex-motorerne PCRE2 (reserveløsningen i Phasis) og Irregexp i V8.
- **dayjs** — dato- og tidsregning er en klassisk kilde til fejl på én enhed, som ingen test262-test fanger. dayjs afprøver konstruktørvarianter, aritmetik over DST-ækvivalente månedsgrænser og udvidelse af formattokens gennem omtrent de samme kodeveje, som alle JS Date-biblioteker bruger.
- **bignumber.js** — aritmetik med vilkårlig præcision uden TypedArrays afprøver strengbaseret talparsing, løkker til multiplikation og division af store heltal samt valg af afrundingstilstand. Alt er ren JS, så motoren bærer hele omkostningen. Afslører selv små fejl i konvertering mellem Number ↔ String.
- **json5** — mere fleksibel JSON-parsing bruger i høj grad regex-tegnklasser og tokenisering med tilstand. En god indikator for både regex-korrekthed og grænsetilfælde ved iteration over strenge.
- **fuse.js** — en UMD transpileret med Babel, der afprøver `_classCallCheck` (mønstret `this instanceof Ctor`, som alle klasser transpileret til JS-versioner før ES6 bruger) samt hele bitap-algoritmen til omtrentlige match. Denne struktur går igen i alle biblioteker transpileret med Babel, så fejl i Fuse rammer halvdelen af npm-økosystemet.
- **handlebars** — en komplet skabelonmotor, der først kompilerer og derefter renderer. Afprøver kørselsvejen uden `eval` gennem ét stort `compile()`-indgangspunkt, gennemløb af AST, opslag af hjælpefunktioner i en dynamisk tabel og kontrol af typen `SafeString` med `instanceof` på tværs af realms. En kontrast til den enklere skabelonfortolker i mustache.js.
- **zod** — skemavalidering ved kørsel. Store klassehierarkier (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) med metodekæder, der returnerer mere specifikke underklasser, struktureret fejlformatering, hvor formen på `.issues`-arrayet på JS-siden skal være byte-identisk med Node, og mønstre med diskriminatorer og bogstavelige tags. Afprøver den type objektorienteret valideringskode, som omgiver halvdelen af moderne TypeScript-apps.
- **typescript** — den *faktiske* TypeScript-kompiler, der kører på den indlejrede motor. 9 MB minificeret kompiler, som genparser vilkårlig TS, gennemløber AST og genererer JS: den tungeste tænkelige arbejdsbyrde i ren JS. Hvis Phasis kan transpilere generics, async/await, enums og klassehierarkier byte-identisk med `tsc`, er sprogsemantikken solid.
- **prettier** — en JS-formatter med faste formateringsvalg. At formatere JS *med* JS betyder, at alle hjørnetilfælde i specifikationen, som motoren understøtter, berøres af den samme kontrolstruktur, der formaterer din kode: en usædvanligt krævende arbejdsbyrde.
- **svelte/compiler** — den selvstændige kompiler fra Svelte. Parser `.svelte`-kildekode, gennemløber AST og genererer JS til både klient- og SSR-mål.
- **terser / @babel/parser / postcss** — JS-minifier, JS-parser, CSS-efterbehandler. Titusindvis af linjer minificeret kode, der genparses med vilkårligt input — det er her, sjældne AST-former dukker op.
- **ajv** — JSON-skemavalidator, der JIT-kompilerer hvert skema til en brugerdefineret validatorfunktion via `new Function(...)`. Tester den sti gennem Function-konstruktøren, som de fleste skema- og skabelonbiblioteker bygger på.
- **mobx** — proxybaseret reaktiv tilstand. Hver læsning af en observable går gennem en Proxy `get`-fælde, der registrerer en afhængighed; hver skrivning udløser reaktioner. En stresstest af Proxy-infrastrukturen, observable Maps, arrays og indlejrede objekter samt autorun-planlæggeren.
- **cheerio / htmlparser2** — jQuery på serversiden oven på en hurtig HTML-parser. Parsing med selector-motoren, DOM-lignende gennemgang, attributmanipulation og HTML-serialisering i én pakke.
- **graphql-js / jsonata** — GraphQL-referenceimplementering og et JSON-forespørgselssprog. Begge arbejder intensivt med skemaer, validering og rekursive evalueringer — typisk kode til et datalag i browseren.
- **JSZip** — asynkron ZIP-arkivbygger. Arbejdet planlægges via `setImmediate` og skaber reelt binært output, så både timerfladen og de `Uint8Array`-tunge stier testes.
- **moment / luxon** — dato- og tidsregning. moment er en muterbar, håndoptimeret UMD; luxon er den moderne, immutable omskrivning. Sammen dækker de hele fladen for formatering, parsing og tidszoneækvivalent måneds- og årsregning.
- **mqtt-packet** — ren JS MQTT 3.1.1 / 5.0-codec. Pakning og afkodning på byteniveau samt regex-tegnklasser til base64-ikke-alfabetet, der tester Annex-B-grammatikkanter.
- **xstate / valtio / nanostores / jotai / redux-saga** — det moderne udvalg af tilstandsstyring. Tilstandsmaskiner, proxystat, atomlagre, afledte atomer og generatorbaserede effektkørsler — hvert bibliotek rammer en forskellig form for reaktivitet.
- **escodegen / acorn-walk / estraverse / magic-string** — AST-værktøjer. Kodegenerering, gennemgang og ikke-destruktiv redigering af kildekode — byggestenene til enhver JS-på-JS-transformer (byggeværktøjer, codemods, linters).
- **papaparse / lunr / yaml / sax / css-tree** — rene parsere og tokenizere. CSV, fuldtekstsøgeindeks, YAML 1.2, streaming af SAX-lignende XML og CSS AST. Forskellige grammatikker, alle gode indikatorer for scanning på tegnniveau og regex-adfærd.

## Tilføj flere

Tilføj en ny mappe under `tests/Popular/<name>/` med strukturen på tre filer, og kør derefter:

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

PHPUnit-testpakken finder den automatisk ved næste kørsel, og CI tager den med, fordi ændringen berører `tests/Popular/`.

Gode kandidater at tilføje: `chevrotain` (parserkombinator, tester closures og regex), `nanoid` (grænsen for kryptografi og tilfældighed), `date-fns` (tidszoneflade ud over dayjs).
