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

Вступ

Phasis — це рушій JavaScript, написаний лише на PHP. Він виконує лексичний аналіз, розбирає та виконує ECMAScript у процесі хоста PHP — без exec('node …'), без FFI та без власного бінарного розширення. Потрібні три стандартні розширення PHP: ext-mbstring, ext-bcmath і ext-curl (транспорт fetch() за замовчуванням). ext-intl і ext-openssl необов’язкові. Інформацію про збірки без bcmath див. у розділі Початок роботи.

  • Вбудовуваність — додайте середовище виконання JS до будь-якого застосунку PHP, фреймворку чи інструмента CLI через клас Phasis\Engine.
  • Відповідність специфікації — проходить офіційний набір тестів test262 на 100 %, усі категорії, без пропусків.
  • Веб-API — повний пакет вебплатформи (URL, TextEncoder/Decoder, atob/btoa, structuredClone, performance, DOMException), повний пакет Fetch (fetch, Request, Response, Headers, Body, AbortController/Signal, Blob, File, FormData, EventTarget, повний набір потоків WHATWG, navigator), а також crypto + SubtleCrypto, WebSocket, XMLHttpRequest і справжній цикл подій. Проходить 100 % імпортованих тестів вебплатформи.
  • Сучасний синтаксис — стрілкові функції, класи, async/await, Promises, генератори, Symbol, BigInt, Proxy, Reflect, Temporal, Intl, TypedArrays, повна підтримка модулів.
  • Взаємодія PHP↔JS — передавайте скаляри й масиви PHP до JS (масиви копіюються), прив’язуйте замикання PHP як функції JS і викликайте функції JS з PHP. Об’єктами PHP поки що не можна спільно користуватися з JS; див. Спільні об’єкти.

Для чого створено Phasis

Застосунки PHP, яким потрібно виконувати наданий користувачем код JavaScript — шаблонізатори, прокладки для SSR інтерфейсу, правила перевірки даних, ізольовані середовища для вмісту, безінтерфейсні тестові засоби — зазвичай запускають окремо Node.js або відмовляються від цієї можливості. Обидва варіанти ускладнюють експлуатацію: друге середовище виконання, межа серіалізації, мережа каналів підпроцесів і складнощі безпечного розгортання на спільному хостингу.

Phasis усуває цю прогалину. Ваш код PHP може виконувати лексичний аналіз, розбирати та виконувати JavaScript, використовуючи лише PHP 8.2+ із mbstring, bcmath та curl. Рушій постачається як пакет Composer і має компактний інтерфейс API.

Що він робить

  • Реалізує повну стандартну бібліотеку ECMAScript: Array, String, Object, Math, JSON, Date, RegExp, Map, Set, Promise, Proxy, Reflect, Symbol, BigInt, TypedArray, Temporal, Intl, генератори, асинхронні ітератори, модулі.
  • Надає API вебплатформи, наявність яких реальні бібліотеки JS перевіряють заздалегідь: URL, URLSearchParams, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException. Повний перелік див. у розділі Веб-API.
  • Постачається з fetch і повним сімейством Fetch: Request, Response, Headers, споживачі тіла відповіді, AbortController/AbortSignal, Blob, File, FormData, EventTarget/Event і повний набір потоків WHATWG (ReadableStream, WritableStream, TransformStream, BYOB, стратегії черги). Справжній HTTP працює відразу завдяки PHP та його ext-curl.
  • Постачається з crypto і повним SubtleCrypto (сімейство SHA, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (RFC 6455 і змінний транспорт) та XMLHttpRequest (побудованим на тому самому транспорті fetch).
  • Має справжній цикл подій: setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, а також AsyncContext зі стадії 3 для передавання значень через асинхронні межі.
  • Підтримує сучасний синтаксис: деструктуризацію, spread/rest, обчислювані властивості, опціональний ланцюжок, об’єднання з nullish, шаблонні рядки, теговані шаблони, класи (із приватними полями, статичними блоками, декораторами), top-level await.
  • Перетворює значення на межі PHP↔JS. Скалярні значення й масиви копіюються під час передавання, функції PHP стають функціями JS, а результати JS повертаються як скаляри й масиви PHP. Точні правила див. у розділі Перетворення значень.
  • Виконується під контролем хоста. Хост керує транспортом fetch і хуками політик, цикл подій працює у віртуальному часі, а фіксований ліміт глибини стека викликів зупиняє нескінченну рекурсію. Ліміт ітерацій циклу є, але поки що не застосовується до циклів, які виконує байткодова ВМ; обмежень довжини рядка, виводу чи реального часу немає. Див. API: setLimit.
  • Перевіряється за допомогою Node.js (V8). CI запускає модульні тести й тести-оракули після кожного надсилання змін до main та кожного запиту на злиття, а тести вебплатформи й набори тестів популярних пакетів — коли змінюється вихідний код рушія; повну матрицю test262 запускають вручну, а її знімок додають до COMPAT.md. Див. Сумісність.

Чим цей інструмент не є

Phasis — це не JIT-компілятор. Це інтерпретатор із обходом дерева та опортуністичною віртуальною машиною байткоду. Для навантажень, обмежених диспетчеризацією, очікуйте приблизно 100× часу виконання порівняно з V8. Компроміс — відсутність залежностей, реалізація лише на PHP і виконання під контролем хоста: це ідеально для вбудовування JavaScript у застосунки PHP, де правильність і ізоляція важливіші за максимальну пропускну здатність.

З чого почати

  • Початок роботи — встановлення та запуск першого скрипту.
  • CLI — bin/phasis для запуску файлів, обчислення вихідного коду й виведення AST.
  • API — вбудовування Phasis\Engine у застосунок PHP.
  • Взаємодія — передавання значень PHP і функцій до JavaScript.
  • Сумісність — покриття test262 і підтримувані можливості.
  • Парсер — розбір JavaScript у типізоване AST або ESTree без виконання.
  • Форматувальник — форматування JavaScript, JSON і CSS з компонуванням, сумісним із prettier.
  • Додаткові теми — архітектура, байткодова ВМ, бенчмарки й модель тестування з оракулом.