
# Відомі обмеження

Phasis прагне відповідати V8 у кожному тесті специфікації, який перевіряє спостережувану поведінку. На цій сторінці описано випадки, коли на практиці ця відповідність припиняється — зазвичай через фундаментальні відмінності між інтерпретатором PHP з обходом дерева та рушієм на C++ із JIT-компіляцією.

## Межа продуктивності

Рушій обходить дерево, має байткодову віртуальну машину для окремих випадків і транспілятор JsToPhp, який перетворює тіла з великою кількістю числових операцій або локальних змінних (зокрема форми `obj.method()`, `new Ctor()` і `this.member`) на нативні замикання PHP, які трасувальний JIT у PHP 8.5 може компілювати в машинний код. Більшість інтенсивних операцій диспетчеризації відбувається в циклі switch віртуальної машини або безпосередньо в коді PHP, скомпільованому JIT, а не під час обходу AST. Проте кожен код віртуальної машини все одно має накладні витрати на диспетчеризацію PHP, а форми, які JsToPhp поки не підтримує, повертаються до повільнішої віртуальної машини. Для навантажень, обмежених диспетчеризацією, межа продуктивності становить приблизно **у 100× разів повільніше за V8**.

Для сценаріїв вбудовування — виконання наданої користувачем логіки над даними PHP, конвеєрів перетворення вмісту, правил перевірки — ця межа рідко має значення. V8 — 100 мс; Phasis — 10 с; обидва показники значно нижчі за час очікування запиту. Щоб ще скоротити відставання, потрібно навчити JsToPhp підтримувати більше форм (виведення типів параметрів, перетворення `await` / `yield*`) або генерувати опкоди opcache напряму, а не через `eval()`. Див. [Тести продуктивності § План розвитку](https://phasis.inline0.dev/uk/docs/advanced/benchmarks#roadmap).

## Паралельність кількох агентів

Модель `SharedArrayBuffer` + `Atomics.wait` + `postMessage` у JavaScript передбачає, що хост може запускати справжні потоки ОС. PHP цього не може (без `pcntl_fork`, яке доступне не на всіх хостах).

Phasis імітує одного агента: `Atomics.wait` одразу повертає «not-equal» або «timed-out», а `notify` завжди повертає 0. Це проходить усі тести test262 для одного агента (перевірка вхідних даних, сценарії помилок, сповіщення без дії), що охоплює 376 із 376 тестів Atomics.

Тести, для яких потрібні два агенти, що працюють паралельно й спостерігають один за одним, не підтримуються. Для справжнього паралельного виконання використовуйте чергу робіт на рівні PHP (Redis, Beanstalkd тощо).

## Семантика середовищ виконання

`ShadowRealm` реалізовано, але кожне дочірнє середовище виконується в тому самому процесі PHP, що й хост. Хост-функції можуть передавати посилання між середовищами, якщо не подбати про ізоляцію коду PHP. Специфікація це дозволяє; V8 забезпечує суворішу ізоляцію за допомогою окремих екземплярів v8::Isolate.

`createRealm()` (хост-перехоплювач test262) створює новий `Phasis\Engine` усередині й передає стандартну бібліотеку через міст.

## Вибір рушія регулярних виразів

Phasis використовує PCRE2 з PHP як основний рушій регулярних виразів, а для випадків, які PCRE2 не може обробити точно, — власний механізм зіставлення (захоплення в перегляді назад, квантифіковані групи зі скиданням, певні нюанси прапорців `/v`). Власний механізм повільніший за PCRE2 і використовується лише тоді, коли диспетчер виявляє несумісний шаблон.

Помітний наслідок: PCRE2 може використовувати таблицю згортання регістру, відмінну від таблиці у версії ICU V8, особливо у старіших дистрибутивах Linux (Ubuntu 22.04 постачається з ICU 70; Phasis додає таблицю згортання ICU 76+, щоб нівелювати відмінності хост-системи в шаблонах `/iu`).

## Модель пам’яті

Збірка сміття з підрахунком посилань у PHP відрізняється від трасувального збирача V8. Об’єкти PHP, захоплені замиканнями хоста, залишаються живими, доки рушій утримує ці замикання, а цикли між ними не збираються, доки не буде знищено `Engine`. Для кешів, які не потрібно утримувати в пам’яті, використовуйте `WeakMap` / `WeakRef`.

`process.memoryUsage()` та подібні API інтроспекції, специфічні для V8, не реалізовані.

## Завантажувач модулів

Завантажувач ES-модулів обробляє відносні імпорти на основі файлової системи, але не розуміє домовленостей пакувальників:

- Розв’язання `node_modules` відсутнє.
- Карта `package.json` `exports` відсутня.
- Визначення розширення файлу не виконується (потрібно писати `import './foo.mjs'`, а не `import './foo'`).
- Імпорт HTTP не підтримується.

Це відповідає специфікації ECMAScript без додаткових домовленостей, але не поведінці Node. Гачка для власного розв’язувача модулів немає. Щоб використовувати пакети npm, перед передаванням у Phasis зберіть їх за допомогою такого інструмента, як esbuild, в один скрипт або модуль.

## Wasm

`WebAssembly` не реалізовано. Немає середовища виконання wasm PHP, до якого можна прив’язатися.

## Пропущені API, доступні лише в браузері

Phasis постачається з повним Web Platform Pack (`URL`, `TextEncoder`/`TextDecoder`, `atob`/`btoa`, `structuredClone`, `performance`, `DOMException`), повним Fetch Pack (`fetch`, `Request`, `Response`, `Headers`, `Body`, `AbortController`/`AbortSignal`, `Blob`/`File`, `FormData`, `EventTarget`/`Event`, повним WHATWG Streams, `navigator`), а також `crypto` (`getRandomValues`, `randomUUID`, повний `SubtleCrypto`: дайджест, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), `WebSocket` (конструктор + кодек кадрів RFC 6455, транспорт можна замінити), `XMLHttpRequest` (працює поверх транспорту fetch) і справжній цикл подій (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `queueMicrotask`, `AsyncContext`). Див. [веб-API](https://phasis.inline0.dev/uk/docs/compatibility/web-apis).

Що *не* постачається:

- `window`, `document`, дерево DOM — Phasis не є браузером.
- `localStorage`, `sessionStorage`, `IndexedDB` — це відповідальність хоста; вбудовувач відповідає за збереження даних.
- `Worker`, `SharedWorker`, `MessageChannel` — потрібні справжні потоки ОС, яких PHP не надає.
- Service Workers, Push API, Notifications, BroadcastChannel — поза браузером не мають сенсу.

## Глобальні об’єкти Node

`process`, `Buffer`, `__dirname`, `__filename`, `require()` — тут їх теж немає. Це домовленості хост-середовища Node, а не можливості мови.

Якщо ви переносите код Node, замініть `require('foo')` на `import 'foo'`, замініть `process.env.X` на `env.X`, прив’язаний до хоста, і передавайте шляхи, еквівалентні `__dirname`, із PHP.

## Точність десяткових чисел

Числа ECMAScript — це числа з рухомою комою подвійної точності IEEE 754. Десяткова арифметика з понад 15 значущими цифрами втрачає точність так само, як і в будь-якому іншому рушії JS. Для точної арифметики з цілими числами використовуйте `BigInt`, а для точної арифметики з дробами — десяткову бібліотеку JS.

PHP використовує внутрішньо `bcmath` для `BigInt`; єдина реальна відмінність від V8 у тому, що дуже великі операції з bigint у PHP повільніші, ніж у реалізації C++ в V8. Точність обчислень однакова.
