
# Populära paket

Att följa specifikationen garanterar inte att verkliga bibliotek fungerar. JS-motorer som klarar 99 % av test262 går ändå ofta sönder med produktionskod eftersom biblioteken är beroende av många mindre uppenbara specifikationsdetaljer — Proxy-fällor i en viss ordning, formen på `Function.prototype.toString`, regexbeteende för knepiga indata och exakt hur ordningen på `Object.keys` samspelar med beräknade egenskapsnamn.

Phasis verifierar **204 vanliga bibliotek** byte för byte mot Node.js (V8). De finns i `tests/Popular/` i kodarkivet, och CI kör dem varje gång motorkällkoden eller sviten ändras.

## Täckning per kategori

| Kategori | Bibliotek |
|---|---|
| **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 |
| **Mall / 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 |
| **Verktyg / funktioner** | 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 |
| **Objektåtkomst** | 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 / 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 / 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 |
| **Hashning / 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ökning / 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 / dataformat** | 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 |
| **Strängar / språk** | 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 / webb** | 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 |
| **Färg** | 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 / likhet** | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| **Format / visning** | ms 2.1.3, bytes 3.1.2 |
| **ID:n / UUID:er** | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| **Typidentifiering / 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 |
| **Cache / prestanda** | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| **Asynkronitet / 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 |
| **Reaktivt tillstånd** | 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 |
| **Bygge / AST / kompilatorer** | 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 / protokoll** | mqtt-packet 9.0.4 |
| **GraphQL** | graphql-js 16.11.0 |
| **Syntaxmarkering** | highlight.js 11.11.1 |
| **Test / assertioner** | chai 6.2.1 |

Totalt: **204 bibliotek** återger alla exakt samma utdata som Node. Alla är låsta till den senaste uppströmsversionen vid den senaste uppdateringen.

## Så fungerar det

Varje scenario är en katalog `tests/Popular/<lib>/` 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` är ett data-provider-test PHPUnit som:

1. Läser in `lodash.js` + `runner.js` i en ny `new Phasis\Engine()`.
2. Fångar utdata från `console.log` i en buffert.
3. Kontrollerar att den fångade bufferten är byte för byte identisk med `oracle.txt`.

Återskapa en referens med:

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

(Används när du uppdaterar det inbäddade biblioteket — kör programmet igen under riktig Node och skriver över `oracle.txt`.)

## CI-kontroll

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

Körs vid pushar och pull-förfrågningar till `main` som ändrar `src/`, `tests/Popular/`, `phpunit.xml.dist`, filerna Composer eller själva arbetsflödet, samt vid manuell start. Två steg:

1. **Sidan Phasis** — kör PHPUnit `popular`-testsviten, som kör varje bibliotek genom Phasis och jämför med den incheckade referensen. Misslyckas om en enda byte skiljer sig.
2. **Ny kontroll med Node** — kör `node tests/Popular/gen-oracle.js …` mot varje bibliotek och verifierar att den nygenererade referensen stämmer med den incheckade. Upptäcker avvikelser där ”det inbäddade biblioteket har uppdaterats utan att referensen uppdaterats”.

Båda måste godkännas innan PR:en kan slås ihop. En förbättring i test262 som får lodash att sluta fungera är oacceptabel; en förbättring i lodash som får test262 att sluta fungera är inte heller acceptabel.

## Varför dessa bibliotek

- **acorn** — parsning är den känsligaste delen av varje JS-motor. Biblioteket prövar alla syntaktiska specialfall som modern JS tillför. Om Phasis kan tolka godtycklig modern kod med acorn är körmiljön stabil.
- **mustache.js** — mallrendering är ett av de inbäddningsfall som Phasis uttryckligen riktar sig till (det första konkreta exemplet i README är "mallmotorer"). Mustache prövar iteration, uppslagning av variabelomfång och strängomvandlingar i samma ordning som verkliga mallar.
- **lodash** — världens mest använda verktygsbibliotek för JS. Dess över 300 funktioner berör indirekt varje metod i standardbiblioteket. Om lodash fungerar, fungerar generell dataomvandling i JS.
- **marked** — rendering av markdown. Ett praktiskt arbetsflöde som prövar mängder av regex samt stränghantering med tillstånd över radgränser. Det synliggör skillnader mellan PCRE2 (reservmotorn i Phasis) och Irregexp i V8.
- **dayjs** — datum- och tidsaritmetik är en klassisk källa till fel på en enhet som inget test262-fall fångar. dayjs prövar konstruktorvarianter, aritmetik över månadsgränser motsvarande sommartidsgränser och expansion av formateringstoken i ungefär samma kodvägar som alla JS-bibliotek för Date använder.
- **bignumber.js** — aritmetik med godtycklig precision utan TypedArrays prövar strängbaserad talparsning, loopar för multiplikation och division av stora heltal samt val av avrundningsläge — allt i ren JS så att motorn står för hela kostnaden. Det synliggör subtila fel i konverteringen Number ↔ String.
- **json5** — tillåtande JSON-parsning bygger i hög grad på regex med teckenklasser och tillståndsbaserad tokenisering. Ett bra varningstest för både regex-korrekthet och specialfall i strängiteration.
- **fuse.js** — ett Babel-transpilerat UMD-bibliotek som prövar `_classCallCheck` (mönstret `this instanceof Ctor` som varje transpilerad klass från före ES6 använder) samt hela bitap-algoritmen för ungefärlig matchning. Samma struktur återkommer i alla Babel-transpilerade bibliotek, så ett fel som slår ut Fuse slår ut halva npm-ekosystemet.
- **handlebars** — en komplett mallmotor med kompilering följd av rendering. Den prövar körvägen utan `eval` via en enda stor ingång, `compile()`, AST-traversering, anrop av hjälpfunktioner via en dynamisk uppslagstabell och typkontroll av `SafeString` med `instanceof` mellan körkontexter. Ett komplement till den enklare mallvandringen i mustache.js.
- **zod** — schemavalidering vid körning. Omfattande klasshierarkier (`ZodString`, `ZodObject`, `ZodArray`, `ZodUnion`, …) med kedjade metodanrop som returnerar förfinade underklasser, strukturerad felformatering där formen på JS-sidans `.issues`-array måste matcha Node byte för byte samt mönster med diskriminatorer och litterala taggar. Prövar den typ av objektorienterad valideringskod som omger hälften av moderna TypeScript-appar.
- **typescript** — den *verkliga* TypeScript-kompilatorn som körs på den inbäddade motorn. 9 MB minifierad kompilator som tolkar om godtycklig TS, traverserar AST och genererar JS — den tyngsta tänkbara arbetslasten i ren JS. Om Phasis kan transpilera generiska typer, async/await, uppräkningar och klasshierarkier till byteidentiska resultat jämfört med `tsc`, är språksemantiken korrekt.
- **prettier** — en JS-formaterare med bestämda formateringsregler. Att formatera JS *med* JS innebär att varje specialfall i specifikationen som motorn har prövas av samma kontrollflöde som formaterar din kod — en ovanligt krävande arbetslast.
- **svelte/compiler** — den fristående kompilatorn för Svelte. Tolkar `.svelte`-källkod, traverserar AST och genererar JS för både klient- och SSR-mål.

- **terser / @babel/parser / postcss** — minifierare för JS, parser för JS, efterbehandlare för CSS. Tiotusentals rader minifierad kod som parsar om godtyckliga indata — ytan där ovanliga AST-strukturer dyker upp.
- **ajv** — JSON-schemavaliderare som JIT-kompilerar varje schema till en anpassad validatorfunktion via `new Function(...)`. Testar vägen via Function-konstruktorn som de flesta schema- och mallbibliotek använder.
- **mobx** — reaktivt tillstånd baserat på proxyer. Varje läsning av ett observerbart värde går genom en Proxy-`get`-fälla som registrerar ett beroende; varje skrivning utlöser reaktioner. Ett stresstest av Proxy-infrastrukturen, observerbara Map-objekt, arrayer och nästlade objekt samt schemaläggaren för autorun.
- **cheerio / htmlparser2** — jQuery på serversidan ovanpå en snabb HTML-parser. Parsning med selektormotor, DOM-liknande traversering, attributmanipulering och HTML-serialisering i ett paket.
- **graphql-js / jsonata** — GraphQL-referensimplementation och ett JSON-frågespråk. Båda är inriktade på scheman, validering och rekursiva utvärderare — typisk kod för ”datalager i webbläsaren”.
- **JSZip** — asynkron ZIP-arkivbyggare. Styr arbetet genom `setImmediate`-driven schemaläggning och skapar verklig binär utdata, vilket testar både timergränssnittet och vägar med mycket `Uint8Array`.
- **moment / luxon** — datum- och tidsberäkningar. moment är en föränderlig, handoptimerad UMD; luxon är den moderna oföränderliga omskrivningen. Tillsammans täcker de hela området för formatering, parsning och tidszonsmässigt likvärdig månads- och årsaritmetik.
- **mqtt-packet** — ren JS MQTT-3.1.1-codec för version 5.0. Packning och avkodning på bytenivå samt regexar med teckenklasser som omfattar icke-alfabetiska Base64-tecken, vilket testar grammatikens kanter i Annex B.
- **xstate / valtio / nanostores / jotai / redux-saga** — bredden inom modern tillståndshantering. Tillståndsmaskiner, proxytillstånd, atomlager, härledda atomer och generatorbaserade effektkörningar — varje bibliotek träffar en annan form av reaktivitet.
- **escodegen / acorn-walk / estraverse / magic-string** — AST-verktyg. Kodgenerering, traversering och icke-destruktiv källkodsredigering — byggstenarna för alla JS-på-JS-transformerare (byggverktyg, codemods, linters).
- **papaparse / lunr / yaml / sax / css-tree** — rena parsrar och tokeniserare. CSV, fulltextsökindex, YAML 1.2, SAX-liknande strömmande XML och CSS-AST. Olika grammatiker, alla bra lackmustest för teckenskanning och regexbeteende.

## Lägga till fler

Lägg till en ny katalog under `tests/Popular/<name>/` med strukturen för de tre filerna och kör sedan:

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

Testsviten PHPUnit hittar den automatiskt vid nästa körning, och CI tar med den eftersom ändringen berör `tests/Popular/`.

Bra kandidater att lägga till: `chevrotain` (parserkombinator, testar closures och reguljära uttryck), `nanoid` (gränssnittet för kryptografi och slumpmässighet), `date-fns` (tidszonsfunktioner utöver dayjs).
