Ga naar de inhoud

Populaire pakketten

Conformiteit met de specificatie garandeert niet dat echte bibliotheken werken. JS-engines die voor 99 % van test262 slagen, lopen in productie toch vaak vast omdat bibliotheken afhankelijk zijn van een lange reeks 'randgevallen in de specificatie' — Proxy-traps in een specifieke volgorde, de vorm van Function.prototype.toString, regexgedrag bij lastige invoer en de precieze manier waarop de volgorde van Object.keys samenwerkt met berekende propertynamen.

Phasis controleert 204 veelgebruikte bibliotheken byte voor byte tegen Node.js (V8). Ze staan in de repository onder tests/Popular/ en CI voert ze uit telkens wanneer de enginebroncode of de suite verandert.

Dekking per categorie

Categorie Bibliotheken
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
Sjablonen / 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
Hulpmiddelen / functioneel 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
Objecttoegang 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
Validatie / 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 / tijd dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2
Wiskunde / getallen 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 / crypto 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
Zoeken / verschillen 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 / gegevensindelingen 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
Strings / taalkunde 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
Compressie / codering / archief pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1
Kleur 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 / gelijkheid rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2
Opmaak / weergave ms 2.1.3, bytes 3.1.2
ID's / UUID's uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3
Typeherkenning / 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 / configuratie semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0
Caches / prestaties lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0
Asynchroon / gebeurtenissen 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
Reactieve status 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 / compilers 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 / protocol mqtt-packet 9.0.4
GraphQL graphql-js 16.11.0
Syntaxaccentuering highlight.js 11.11.1
Testen / assertions chai 6.2.1

Totaal: 204 bibliotheken reproduceren exact dezelfde uitvoer als Node. Alle bibliotheken zijn vastgezet op de nieuwste upstreamversie van de laatste update.

Werking

Elk scenario is een tests/Popular/<lib>/-map met drie bestanden:

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 is een test met gegevensprovider in PHPUnit die:

  1. lodash.js + runner.js laadt in een nieuwe new Phasis\Engine().
  2. De uitvoer van console.log opvangt in een buffer.
  3. Controleert of de opgevangen buffer byte voor byte gelijk is aan oracle.txt.

Een oracle opnieuw genereren:

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

(Wordt gebruikt wanneer u de meegeleverde bibliotheek bijwerkt — voert de runner opnieuw uit onder echte Node en overschrijft oracle.txt.)

CI-controle

Workflow: .github/workflows/popular.yml.

Wordt uitgevoerd bij pushes en pull requests naar main die src/, tests/Popular/, phpunit.xml.dist, de bestanden in Composer of de workflow zelf wijzigen, en bij handmatige uitvoering. Twee stappen:

  1. Kant van Phasis — voert de PHPUnit-popular-testsuite uit, die elke bibliotheek via Phasis uitvoert en vergelijkt met de vastgelegde oracle. Mislukt als ook maar één byte verschilt.
  2. Opnieuw verifiëren met Node — voert node tests/Popular/gen-oracle.js … uit voor elke bibliotheek en controleert of de nieuw gegenereerde oracle overeenkomt met de ingecheckte versie. Spoort afwijkingen op wanneer 'een meegeleverde bibliotheek is bijgewerkt zonder de oracle bij te werken'.

Beide controles moeten slagen voordat de PR wordt samengevoegd. Een verbetering van test262 die lodash breekt, is onaanvaardbaar; een verbetering van lodash die test262 breekt, evenmin.

Waarom deze bibliotheken

  • acorn — parsen is het kwetsbaarste onderdeel van elke JS-engine. Het test alle syntactische randgevallen die moderne JS toevoegt. Als Phasis willekeurige moderne code met acorn kan parsen, is de runtime solide.
  • mustache.js — sjablonen verwerken is een van de toepassingen waarvoor Phasis expliciet bedoeld is (het eerste concrete voorbeeld van README is 'sjabloonengines'). Mustache test iteratie, scope-resolutie en tekenreeksbewerkingen in de volgorde waarin echte sjablonen die uitvoeren.
  • lodash — de meestgebruikte JS-hulpmiddelenbibliotheek ter wereld. De meer dan 300 functies raken indirect elke methode van de standaardbibliotheek. Als lodash werkt, werken algemene JS-gegevensbewerkingen ook.
  • marked — Markdown weergeven. Praktisch en test regex (veel regex) plus tekenreeksbewerkingen met status over meerdere regels. Brengt verschillen tussen regex-engines aan het licht: PCRE2 (de fallback van Phasis) en Irregexp van V8.
  • dayjs — datum- en tijdsberekeningen zijn een klassieke bron van fouten van één dag die geen enkele test van test262 opspoort. dayjs test varianten van constructors, berekeningen over maandgrenzen die overeenkomen door zomertijd en de uitbreiding van formaattokens in ongeveer dezelfde codepaden die elke datum-bibliotheek van JS gebruikt.
  • bignumber.js — rekenen met willekeurige precisie zonder TypedArrays test getalparsing op basis van tekenreeksen, vermenigvuldigings- en delingslussen voor grote gehele getallen en afhandeling van afrondingsmodi — allemaal in zuivere JS, zodat de engine alle kosten draagt. Brengt subtiele fouten aan het licht bij de conversie tussen getallen en tekenreeksen.
  • json5 — het parsen van soepele JSON-syntax steunt sterk op regexen met tekenklassen en tokenisatie met status. Een goede graadmeter voor de juistheid van regex en de omgang met randgevallen bij iteratie over tekenreeksen.
  • fuse.js — een met Babel getranspilde UMD die _classCallCheck test (het this instanceof Ctor-patroon dat elke klasse gebruikt die vóór ES6 is getranspild), plus het volledige bitap-algoritme voor fuzzy matching. Dit is een vorm die elke met Babel getranspilde bibliotheek deelt; alles wat Fuse breekt, breekt dus de helft van het npm-ecosysteem.
  • handlebars — uitgebreide sjablonenverwerking met eerst compileren en daarna weergeven. Test het runtimepad zonder eval via één groot compile()-item, AST-traversal, dispatch van helpers via een dynamische opzoektabel en SafeString-typecontrole die instanceof over verschillende realms gebruikt. Een tegenhanger van de eenvoudigere sjabloonverwerker van mustache.js.
  • zod — schemavalidatie tijdens runtime. Uitgebreide klassehiërarchieën (ZodString, ZodObject, ZodArray, ZodUnion, …) met methodenketens die verfijnde subklassen teruggeven, gestructureerde foutopmaak waarbij de vorm van de array JS-zijde-.issues byte voor byte moet overeenkomen met Node, en patronen met discriminators en letterlijke tags. Test het soort validatiecode met veel objectgeoriënteerde code dat de helft van moderne TypeScript-apps omhult.
  • typescript — de echte TypeScript-compiler die op de ingebedde engine draait. Een compiler van 9 MB met minificatie die willekeurige TS opnieuw parseert, de AST doorloopt en JS produceert — de zwaarste denkbare payload in zuivere JS. Als Phasis generics, async/await, enums en klassehiërarchieën byte voor byte gelijk aan tsc kan transpilen, zijn de taalregels solide.
  • prettier — een eigenzinnige JS-formatter. JS opmaken met JS raakt elk randgeval van de specificatie in de engine via dezelfde besturingsstroom die uw code opmaakt — een bijzonder veeleisende werklast.
  • svelte/compiler — de zelfstandige compiler van Svelte. Parseert .svelte-broncode, doorloopt de AST en produceert JS voor zowel client- als SSR-doelen.
  • terser / @babel/parser / postcss — JS-minifier, JS-parser, CSS-nabewerker. Tienduizenden regels geminificeerde code die willekeurige invoer opnieuw parsen: het oppervlak waar zeldzame AST-vormen opduiken.
  • ajv — JSON-schemavalidator die elk schema JIT compileert tot een aangepaste validatorfunctie via new Function(...). Dit test het Function-constructorpad waar de meeste schema- en templatingbibliotheken op steunen.
  • mobx — proxygebaseerde reactieve status. Elke uitlezing van een observable loopt via een Proxy get-trap die een afhankelijkheid registreert; elke schrijfoperatie activeert reacties. Een stresstest voor de Proxy-infrastructuur, observable Maps / arrays / geneste objecten en de autorun-planner.
  • cheerio / htmlparser2 — jQuery aan de serverzijde boven op een snelle HTML-parser. Selector-engine-parsing, DOM-achtige traversering, attribuutmanipulatie en HTML-serialisatie in één pakket.
  • graphql-js / jsonata — GraphQL-referentie-implementatie en een JSON-querytaal. Beide maken intensief gebruik van schema's, validatie en recursieve evaluatoren: typische code voor een 'datalaag in de browser'.
  • JSZip — asynchrone ZIP-archiefbouwer. Routeert werk via setImmediate-gestuurde planning en produceert echte binaire uitvoer, waarmee zowel het timeroppervlak als Uint8Array-intensieve paden worden getest.
  • moment / luxon — datum- en tijdrekenkunde. moment is mutable en met de hand geoptimaliseerde UMD; luxon is de moderne immutable herschrijving. Samen bestrijken ze het volledige oppervlak van formattering, parsing en tijdzone-equivalente maand- en jaarberekeningen.
  • mqtt-packet — pure-JS MQTT 3.1.1 / 5.0-codec. Inpakken en decoderen op byteniveau, plus regex-tekenklassen voor tekens buiten het base64-alfabet die grammaticale randgevallen van Annex B testen.
  • xstate / valtio / nanostores / jotai / redux-saga — het moderne aanbod voor statusbeheer. Statusmachines, proxystatus, atomstores, afgeleide atomen en generatorgebaseerde effectuitvoerders: elke bibliotheek raakt een andere vorm van reactiviteit.
  • escodegen / acorn-walk / estraverse / magic-string — AST-tools. Codegeneratie, traversering en niet-destructieve bronbewerking: de bouwstenen voor elke JS-op-JS-transformator (buildtools, codemods, linters).
  • papaparse / lunr / yaml / sax / css-tree — pure parsers en tokenizers. CSV, full-textzoekindex, YAML 1.2, streaming SAX-achtige XML en CSS-AST. Verschillende grammatica's, allemaal goede kanaries voor scannen op tekenniveau en regexgedrag.

Meer toevoegen

Voeg een nieuwe map met de structuur van drie bestanden toe onder tests/Popular/<name>/ en voer daarna het volgende uit:

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

De PHPUnit-suite ontdekt deze automatisch bij de volgende uitvoering, en CI neemt deze mee omdat de wijziging tests/Popular/ raakt.

Goede kandidaten om toe te voegen: chevrotain (parsercombinator, test closures + regex), nanoid (grensgebied van cryptografie en willekeurigheid), date-fns (tijdzonefunctionaliteit buiten dayjs).