Перейти до вмісту

Популярні пакети

Відповідність специфікації не гарантує, що реальні бібліотеки працюватимуть. Рушії 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>/ із трьома файлами:

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 — це тест постачальника даних PHPUnit, який:

  1. Завантажує lodash.js + runner.js у новий new Phasis\Engine().
  2. Записує вивід console.log у буфер.
  3. Перевіряє, що вміст буфера побайтно збігається з oracle.txt.

Перегенеруйте еталон за допомогою:

Командна оболонка
node tests/Popular/gen-oracle.js tests/Popular/<lib>

(Використовується під час оновлення вендорної бібліотеки — повторно запускає виконавець у справжньому Node і перезаписує oracle.txt.)

Перевірка CI

Робочий процес: .github/workflows/popular.yml.

Запускається після надсилання змін і створення запитів на злиття в main, якщо вони змінюють src/, tests/Popular/, phpunit.xml.dist, файли Composer або сам робочий процес, а також запускається вручну. Два кроки:

  1. Сторона Phasis — запускає набір тестів PHPUnit popular, який виконує кожну бібліотеку через Phasis і порівнює результат із зафіксованим еталоном. Помилка виникає, якщо відрізняється хоча б один байт.
  2. Повторна перевірка в Node — запускає node tests/Popular/gen-oracle.js … для кожної бібліотеки й перевіряє, що щойно згенерований еталон збігається з тим, що збережено в репозиторії. Виявляє розбіжність, коли «вендорну бібліотеку оновили, але еталон не оновили».

Обидві перевірки мають пройти до злиття 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 охоплює варіанти конструктора, арифметику через межі місяців, еквівалентні переходу на літній час, і розгортання токенів форматування приблизно тими самими шляхами коду, що й будь-яка бібліотека дат JS.
  • bignumber.js — арифметика довільної точності без TypedArrays перевіряє розбір чисел із рядків, цикли множення та ділення великих цілих чисел і вибір режиму округлення — усе на чистому JS, тож рушій бере на себе всі витрати. Виявляє будь-які непомітні порушення перетворення Number ↔ String.
  • json5 — розбір невимушеного формату JSON значною мірою покладається на регулярні вирази з класами символів і токенізацію зі станом. Це вдалий індикатор правильності regex і крайових випадків ітерації рядків.
  • fuse.js — UMD, транспільований Babel, який перевіряє _classCallCheck (шаблон this instanceof Ctor, який використовує кожен транспільований клас до ES6), а також повний алгоритм нечіткого пошуку bitap. Це типова структура для бібліотек, транспільованих Babel, тож усе, що ламає Fuse, ламає половину екосистеми npm.
  • handlebars — повнофункціональна шаблонізація з компіляцією перед рендерингом. Перевіряє шлях виконання без eval через один великий запис compile(), обхід AST, виклик допоміжних функцій через динамічну таблицю пошуку та перевірку бренду SafeString, яка використовує instanceof між різними realm. Для порівняння з простішим обхідником шаблонів у mustache.js.
  • zod — перевірка схем під час виконання. Глибокі ієрархії класів (ZodString, ZodObject, ZodArray, ZodUnion, …) із ланцюжками методів, що повертають уточнені підкласи; форматування структурованих помилок, у якому форма масиву .issues на боці JS має побайтово збігатися з Node; а також шаблони дискримінаторів і літеральних тегів. Перевіряє код із насиченим ООП для валідації, який лежить в основі половини сучасних застосунків TypeScript.
  • typescript — справжній компілятор TypeScript, що працює у вбудованому рушії. Це 9 MB мінімізованого компілятора, який повторно розбирає довільний TS, обходить AST і генерує JS — найважчий можливий тягар на чистому JS. Якщо Phasis може транспілювати узагальнення, async/await, перелічення та ієрархії класів із побайтовою відповідністю до 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 — MQTT-кодек JS 3.1.1 / 5.0. Пакування й декодування на рівні байтів, а також класи символів регулярних виразів для символів поза алфавітом base64, що перевіряють граничні випадки граматики Annex B.
  • xstate / valtio / nanostores / jotai / redux-saga — широкий спектр сучасних засобів керування станом. Автомати станів, стан на основі проксі, сховища атомів, похідні атоми, виконавці ефектів на основі генераторів — кожна бібліотека охоплює окрему форму реактивності.
  • escodegen / acorn-walk / estraverse / magic-string — інструменти для AST. Генерація коду, обхід і недеструктивне редагування джерела — основа будь-якого трансформера JS-на-JS (інструментів збирання, кодмодів, лінтерів).
  • papaparse / lunr / yaml / sax / css-tree — чисті парсери й токенізатори. CSV, індекс повнотекстового пошуку, YAML 1.2, потоковий XML у стилі SAX і 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).