Популярни пакети
Съответствието със спецификацията не гарантира, че реалните библиотеки ще работят. Енджини на JS, които преминават 99 % от test262, все пак редовно се провалят при продукционен код, защото библиотеките зависят от дълга поредица от „ъглови случаи“ в спецификацията — капани на Proxy в определен ред, структура на Function.prototype.toString, поведение на regex при сложни входни данни и точното взаимодействие между подредбата на Object.keys и изчисляемите имена на свойства.
Phasis проверява 204 широко използвани библиотеки байт по байт спрямо Node.js (V8). Те се намират в tests/Popular/ в хранилището, а CI ги изпълнява при всяка промяна в изходния код на енджина или тестовия набор.
Покритие по категории
| Категория | Библиотеки |
|---|---|
| Парсери / 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 |
| Шаблонизиране / 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 |
| Помощни / функционални | 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 |
| Достъп до обекти | 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 |
| Валидиране / схеми | 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 |
| Дата / час | dayjs 1.11.20, date-fns 4.1.0, timeago.js 4.0.2, luxon 3.7.3, moment 2.30.2 |
| Математика / числа | 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 |
| Хеширане / криптография | 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 |
| Търсене / разлики | 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 / формати на данни | 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 |
| Низове / лингвистика | 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 / уеб | 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 |
| Компресиране / кодиране / архиви | pako 2.1.0, lz-string 1.5.0, base64-js 1.5.1, JSZip 3.10.1 |
| Цветове | 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 |
| Клониране / равенство | rfdc 1.4.1, klona 2.0.6, fast-copy 3.0.2 |
| Форматиране / показване | ms 2.1.3, bytes 3.1.2 |
| Идентификатори / UUID | uuid 10.0.0, hexoid 2.0.0, ulid 3.0.1, cuid2 2.2.2, short-unique-id 5.4.3 |
| Определяне на тип / 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 / конфигурация | semver 7.6.3, compare-versions 6.1.1, semver-compare 1.0.0 |
| Кешове / производителност | lru-cache 11.0.2, marky 1.3.0, array-flatten 3.0.0, arr-diff 4.0.0 |
| Асинхронност / събития | 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 |
| Реактивно състояние | 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 / стилове | postcss 8.5.7, stylis 4.3.6, css-tree 3.0.4 |
| Компилация / AST / компилатори | 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 (компилатор), typescript 6.0.3 |
| MQTT / протоколи | mqtt-packet 9.0.4 |
| GraphQL | graphql-js 16.11.0 |
| Оцветяване на синтаксиса | highlight.js 11.11.1 |
| Тестване / проверки | chai 6.2.1 |
Общо: 204 библиотеки възпроизвеждат точно изхода на Node. Всички са фиксирани към най-новото издание на upstream към последното им обновяване.
Как работи
Всеки сценарий е директория tests/Popular/<lib>/ с три файла:
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 е тест с доставчик на данни по PHPUnit, който:
- Зарежда
lodash.js+runner.jsв новnew Phasis\Engine(). - Записва изхода на
console.logв буфер. - Проверява дали записаният буфер съвпада побайтно с
oracle.txt.
Регенерирайте oracle с:
node tests/Popular/gen-oracle.js tests/Popular/<lib>
(Използва се при обновяване на включената библиотека — изпълнява runner отново в реален Node и презаписва oracle.txt.)
Проверка в CI
Работен процес: .github/workflows/popular.yml.
Изпълнява се при push и pull request към main, които променят src/, tests/Popular/, phpunit.xml.dist, файловете на Composer или самия workflow, както и при ръчно стартиране. Има две стъпки:
- В страната на Phasis — изпълнява набора от тестове PHPUnit
popular, който стартира всяка библиотека чрез Phasis и сравнява резултата с записания oracle. Провалът настъпва дори при разлика от един байт. - Повторна проверка с Node — изпълнява
node tests/Popular/gen-oracle.js …за всяка библиотека и проверява дали новогенерираният oracle съвпада със записания. Така се открива разминаване, когато „включена библиотека е обновена без обновяване на oracle“.
И двете проверки трябва да преминат, преди PR да бъде слят. Не е приемливо подобрение в test262 да наруши lodash, нито подобрение за lodash да наруши test262.
Защо са избрани тези библиотеки
- acorn — парсването е най-крехката част на всеки енджин на JS. То изпитва всеки синтактичен граничен случай, добавен в съвременния JS. Ако Phasis може да парсва произволен съвременен код с acorn, средата за изпълнение е стабилна.
- mustache.js — шаблонизирането е една от употребите при вграждане, към които Phasis изрично се насочва (първият конкретен пример в README е „шаблонизиращи енджини“). Mustache проверява итерацията, разрешаването на обхватите и трансформациите на низове в реда, в който ги извършват реалните шаблони.
- lodash — най-използваната помощна библиотека за JS в света. Нейните над 300 функции засягат транзитивно всеки метод от стандартната библиотека. Ако lodash работи, работят и общите операции за трансформация на данни в JS.
- marked — визуализиране на Markdown. Практичен тест, който проверява regex (в голям обем) и манипулиране на низове със състояние между редовете. Показва разминаванията между regex енджина PCRE2 (резервния на Phasis) и Irregexp на V8.
- dayjs — аритметиката с дата и час е класически източник на грешки с отместване с един ден, които нито един тест в test262 не улавя. dayjs проверява варианти на конструкторите, аритметика през границите на месеци, еквивалентни на DST, и разширяване на токени за форматиране в приблизително същите пътища на кода, които използва всяка библиотека за дати на JS.
- bignumber.js — аритметика с произволна точност без TypedArrays проверява парсване на числа от низове, цикли за умножение и деление на големи цели числа и избор на режим на закръгляне — всичко в чист JS, така че енджинът поема цялата тежест. Така се откриват и фини грешки при преобразуването между Number и String.
- json5 — парсването на по-свободен JSON разчита силно на regex класове от символи и токенизация със състояние. Добър ранен индикатор за коректността на regex и граничните случаи при обхождане на низове.
- fuse.js — UMD, преобразуван от Babel, който проверява
_classCallCheck(шаблонаthis instanceof Ctor, използван от всеки транспилиран клас преди ES6), както и пълния алгоритъм за приблизително съвпадение bitap. Този шаблон е общ за библиотеките, транспилирани с Babel, така че проблемите във Fuse засягат половината от екосистемата на npm. - handlebars — пълнофункционално шаблонизиране с компилиране преди визуализиране. Проверява пътя на средата за изпълнение без
evalчрез един голям входенcompile(), обхождане на AST, извикване на helper-и чрез динамична таблица за търсене и проверка на типа наSafeString, при коятоinstanceofсе използва между среди. За сравнение с по-простия обхождач на шаблони на mustache.js. - zod — валидиране на схеми по време на изпълнение. Сложни йерархии от класове (
ZodString,ZodObject,ZodArray,ZodUnion, …) с верижно извикване на методи, което връща прецизирани подкласове; структурирано форматиране на грешки, при което формата на масива.issuesот страната на JS трябва да съвпада байт по байт с Node; и шаблони с дискриминатори и буквални стойности като тагове. Проверява кода за валидация с интензивно използване на ООП, който стои зад половината съвременни приложения на TypeScript. - typescript — истинският компилатор на TypeScript, изпълняван в вградената среда. 9 MB минифициран компилатор, който парсва произволен TS, обхожда AST и генерира JS — най-тежкия възможен чист payload на JS. Ако Phasis може да транспилира generics, async/await, enums и йерархии от класове така, че резултатът да съвпада байт по байт с
tsc, семантиката на езика е правилна. - prettier — форматер на JS с ясна стилистична позиция. Форматирането на JS с JS задейства всеки граничен случай от спецификацията в енджина чрез същия контролен поток, който форматира кода ви — изключително взискателно натоварване.
- svelte/compiler — самостоятелният компилатор на Svelte. Парсва изходен код на
.svelte, обхожда AST и генерира JS за клиентски и SSR цели. - terser / @babel/parser / postcss — минификатор на JS, парсер на JS, постпроцесор на CSS. Десетки хиляди редове минифициран код, който парсва повторно произволен вход — областта, в която се проявяват редки форми на AST.
- ajv — валидатор на схеми на JSON, който JIT компилира всяка схема до персонализирана функция за валидиране чрез
new Function(...). Тества пътя през конструктора Function, на който разчитат повечето библиотеки за схеми и шаблони. - mobx — реактивно състояние, базирано на проксита. Всяко четене на наблюдаем обект минава през прихващане на Proxy
get, което регистрира зависимост; всяко записване задейства реакции. Стрес тест за инфраструктурата на Proxy, наблюдаемите Map-ове, масиви и вложени обекти, както и планировчика autorun. - cheerio / htmlparser2 — jQuery от страната на сървъра, изграден върху бърз парсер на HTML. Парсване от селекторния механизъм, обхождане в стил DOM, манипулиране на атрибути и сериализация на HTML в един пакет.
- graphql-js / jsonata — референтна имплементация на GraphQL и език за заявки на JSON. И двете разчитат силно на схеми, валидиране и рекурсивни оценители — типичен код за „слой с данни в браузъра“.
- JSZip — асинхронен инструмент за създаване на ZIP архиви. Насочва работата чрез планиране, задвижвано от
setImmediate, и генерира реален двоичен изход, като тества както повърхността на таймерите, така и пътищата с интензивна употреба наUint8Array. - moment / luxon — аритметика с дати и часове. moment е изменяем UMD с ръчна оптимизация; luxon е модерно неизменяемо пренаписване. Заедно покриват целия набор от форматиране, парсване и изчисления за месец/година с еквивалентни часови зони.
- mqtt-packet — чист JS кодек за MQTT 3.1.1 / 5.0. Пакетиране и декодиране на ниво байтове, както и класове знаци в регулярни изрази за base64, които не са от азбуката, и тестват гранични случаи в граматиката на Annex-B.
- xstate / valtio / nanostores / jotai / redux-saga — съвременният набор от решения за управление на състоянието. Машини на състоянията, състояние с проксита, хранилища с атоми, производни атоми, изпълнители на ефекти, базирани на генератори — всяка библиотека тества различна форма на реактивност.
- escodegen / acorn-walk / estraverse / magic-string — инструменти за AST. Генериране на код, обхождане и редактиране на изходния код без разрушаване — градивните елементи за всеки трансформатор JS върху JS (инструменти за компилация, codemod инструменти, линтери).
- papaparse / lunr / yaml / sax / css-tree — чисти парсери и токенизатори. CSV, индекс за пълнотекстово търсене, YAML 1.2, поточен парсер в стил SAX за XML и AST на CSS. Различни граматики, всички подходящи за ранно откриване на проблеми при сканиране на ниво знаци и поведение на регулярни изрази.
Добавяне на още
Добавете нова директория под tests/Popular/<name>/ със структура от три файла, след което:
node tests/Popular/gen-oracle.js tests/Popular/<name> # one-time, generates oracle.txt
git add tests/Popular/<name>
Наборът от тестове PHPUnit я открива автоматично при следващото изпълнение, а CI я включва, защото промяната засяга tests/Popular/.
Добри кандидати за добавяне: chevrotain (парсерен комбинатор, тества затваряния и регулярни изрази), nanoid (граница на криптографията и случайността), date-fns (поддръжка на часови зони отвъд dayjs).