
# Znane ograniczenia

Phasis dąży do identycznego zachowania jak V8 we wszystkich obserwowalnych testach specyfikacji. Ta strona opisuje sytuacje, w których w praktyce ta zgodność się kończy — zwykle z powodu fundamentalnych różnic między interpreterem PHP przechodzącym po drzewie a silnikiem C++ kompilującym kod za pomocą JIT.

## Limit wydajności

Silnik przechodzi po drzewie składniowym, korzysta z optymistycznej maszyny wirtualnej kodu bajtowego oraz transpilatora JsToPhp, który zamienia bloki intensywnie używające wartości liczbowych i zmiennych lokalnych (w tym kształty `obj.method()`, `new Ctor()` i `this.member`) na natywne domknięcia PHP, które kompilujący metodą śledzącego JIT kompilator PHP 8.5 może zamienić na kod maszynowy. Większość gorących ścieżek wykonania przebiega wewnątrz pętli switch maszyny wirtualnej lub bezpośrednio w kodzie PHP skompilowanym przez JIT — bez przechodzenia po AST — jednak każdy kod operacji maszyny wirtualnej nadal wiąże się z narzutem PHP, a kształt, którego JsToPhp jeszcze nie obsługuje, wraca do wolniejszej maszyny wirtualnej. Limit szybkości obciążeń zależnych od czasu obsługi operacji wynosi około **100× mniej niż V8**.

W przypadku osadzonych obciążeń — uruchamiania logiki dostarczonej przez użytkownika na danych PHP, potoków przekształcania treści i reguł walidacji — limit rzadko ma znaczenie. V8 zajmuje 100 ms; Phasis zajmuje 10 s; oba czasy mieszczą się znacznie poniżej limitu czasu żądania. Zmniejszenie różnicy wymagałoby nauczenia JsToPhp obsługi większej liczby kształtów (wnioskowanie o typach parametrów, obniżanie `await` / `yield*`) albo bezpośredniego generowania kodów operacyjnych opcache zamiast przez `eval()`. Zob. [Benchmarki § Plan rozwoju](https://phasis.inline0.dev/pl/docs/advanced/benchmarks#roadmap).

## Współbieżność wielu agentów

Model JavaScript: `SharedArrayBuffer` + `Atomics.wait` + `postMessage` zakłada, że host może uruchamiać prawdziwe wątki systemu operacyjnego. PHP nie może tego robić bez `pcntl_fork`, które nie jest dostępne na każdym hoście.

Phasis symuluje pojedynczego agenta — `Atomics.wait` natychmiast zwraca „not-equal” lub „timed-out”, a `notify` zawsze zwraca 0. Dzięki temu przechodzą wszystkie testy test262 działające z jednym agentem (walidacja wejścia, ścieżki błędów, powiadomienia bez działania), co obejmuje 376 testów Atomics z 376.

Testy wymagające od dwóch współbieżnych agentów wzajemnej obserwacji nie są obsługiwane. Aby uzyskać prawdziwe przetwarzanie równoległe, użyj kolejki zadań na poziomie PHP (Redis, Beanstalkd, …).

## Semantyka realmów

`ShadowRealm` jest zaimplementowane, ale każdy realm potomny działa w tym samym procesie PHP co host. Funkcje hosta mogą przenosić referencje między realmami, jeśli nie zadbasz o odizolowanie kodu PHP. Specyfikacja na to pozwala, ale V8 wymusza ściślejszą izolację dzięki oddzielnym instancjom v8::Isolate.

`createRealm()` (hak hosta test262) tworzy wewnętrznie nowy `Phasis\Engine` i udostępnia w nim bibliotekę standardową.

## Wybór silnika wyrażeń regularnych

Phasis używa PCRE2 od PHP jako głównego zaplecza wyrażeń regularnych, a w przypadkach, których PCRE2 nie obsługuje dokładnie, stosuje własny mechanizm dopasowywania (lookbehind z przechwytywaniem, kwantyfikowane grupy z resetem, określona semantyka flagi `/v`). Własny mechanizm działa wolniej niż PCRE2 i jest używany wyłącznie wtedy, gdy mechanizm wyboru wykryje niezgodny wzorzec.

Istotną konsekwencją jest to, że tablica dopasowywania wielkości liter w PCRE2 może różnić się od wersji ICU w V8, zwłaszcza w starszych dystrybucjach Linux (Ubuntu 22.04 zawiera ICU 70; Phasis dołącza tablicę ICU 76+, aby uniknąć różnic między systemami hosta dla wzorców `/iu`).

## Model pamięci

Garbage collector PHP zliczający referencje różni się od śledzącego kolektora V8. Obiekty PHP przechwycone przez domknięcia hosta pozostają aktywne, dopóki silnik przechowuje te domknięcia, a cykle między nimi nie są usuwane aż do zniszczenia `Engine`. W przypadku pamięci podręcznej, której nie chcesz utrzymywać w pamięci, użyj `WeakMap` / `WeakRef`.

`process.memoryUsage()` i podobne interfejsy introspekcji specyficzne dla V8 nie są zaimplementowane.

## Moduł ładujący

Moduł ładujący ES rozwiązuje ścieżki importów względnych względem systemu plików, ale nie rozumie konwencji bundlerów:

- Brak rozwiązywania `node_modules`.
- Brak mapy `package.json` `exports`.
- Brak wnioskowania o rozszerzeniu pliku (musisz zapisać `import './foo.mjs'`, a nie `import './foo'`).
- Brak importów HTTP.

To zachowanie jest zgodne z podstawową specyfikacją ECMAScript, ale nie z zachowaniem Node. Nie ma haka pozwalającego użyć własnego mechanizmu rozwiązywania modułów. Aby użyć pakietów npm, spakuj je narzędziem takim jak esbuild do pojedynczego skryptu lub modułu przed przekazaniem go do Phasis.

## Wasm

`WebAssembly` nie jest zaimplementowane. Nie ma środowiska uruchomieniowego wasm PHP, z którym można by je powiązać.

## Pomijane internetowe API dostępne tylko w przeglądarkach

Phasis dostarcza pełny **Web Platform Pack** (`URL`, `TextEncoder`/`TextDecoder`, `atob`/`btoa`, `structuredClone`, `performance`, `DOMException`), pełny **Fetch Pack** (`fetch`, `Request`, `Response`, `Headers`, `Body`, `AbortController`/`AbortSignal`, `Blob`/`File`, `FormData`, `EventTarget`/`Event`, pełny WHATWG Streams, `navigator`), a także `crypto` (`getRandomValues`, `randomUUID`, pełny `SubtleCrypto`: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), `WebSocket` (konstruktor + koder ramek RFC 6455 z wymiennym transportem), `XMLHttpRequest` (warstwa nad transportem fetch) oraz prawdziwą pętlę zdarzeń (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `queueMicrotask`, `AsyncContext`). Zob. [API internetowe](https://phasis.inline0.dev/pl/docs/compatibility/web-apis).

Czego *nie* dostarczamy:

- `window`, `document`, drzewo DOM — Phasis nie jest przeglądarką.
- `localStorage`, `sessionStorage`, `IndexedDB` — kwestie po stronie hosta; za trwałość danych odpowiada osadzający.
- `Worker`, `SharedWorker`, `MessageChannel` — wymagają prawdziwych wątków systemu operacyjnego, których PHP nie udostępnia.
- Service Workers, Push API, Notifications, BroadcastChannel — poza przeglądarką nie mają zastosowania.

## Globalne obiekty Node

`process`, `Buffer`, `__dirname`, `__filename`, `require()` — żaden z tych elementów również nie istnieje. To konwencje hosta Node, a nie funkcje języka.

Jeśli przenosisz kod Node, zastąp `require('foo')` elementem `import 'foo'`, zamień `process.env.X` na `env.X` powiązany z hostem i przekaż ścieżki odpowiadające `__dirname` z poziomu PHP.

## Precyzja dziesiętna

Liczby ECMAScript są liczbami zmiennoprzecinkowymi IEEE 754 double. Działania dziesiętne z więcej niż 15 cyframi znaczącymi tracą precyzję, tak jak w każdym innym silniku JS. Użyj `BigInt` do dokładnych obliczeń całkowitoliczbowych albo biblioteki dziesiętnej JS, jeśli potrzebujesz dokładnych obliczeń ułamkowych.

Wewnętrznie PHP używa `bcmath` do obsługi `BigInt`; jedyna rzeczywista różnica w porównaniu z V8 polega na tym, że bardzo duże operacje bigint działają wolniej w PHP niż w implementacji C++ V8. Poprawność numeryczna jest identyczna.
