
# Limitări cunoscute

Phasis urmărește să se comporte identic cu V8 la fiecare test de specificație observabil. Această pagină enumeră situațiile în care identitatea nu se păstrează în practică — de obicei din cauza diferențelor fundamentale dintre un interpretor PHP care parcurge arborele și un motor C++ compilat JIT.

## Limita de performanță

Motorul parcurge arborele și include o mașină virtuală bytecode oportunistă și un transpiler JsToPhp, care transformă corpurile cu multe operații numerice / variabile locale (inclusiv forme `obj.method()`, `new Ctor()` și `this.member`) în închideri native PHP pe care JIT-ul cu urmărire din PHP 8.5 le poate compila în cod mașină. Cea mai mare parte a distribuirii pe căile fierbinți are loc în bucla switch a mașinii virtuale sau direct în PHP compilate JIT — nu prin parcurgerea AST-ului — însă fiecare instrucțiune a mașinii virtuale plătește în continuare costul distribuirii PHP, iar orice formă pe care JsToPhp nu o gestionează încă revine la mașina virtuală mai lentă. Pentru sarcinile limitate de distribuire, plafonul este de aproximativ **~100× mai lent decât V8**.

Pentru sarcinile de încorporare — rularea logicii furnizate de utilizator pe date PHP, fluxuri de transformare a conținutului, reguli de validare — plafonul contează rareori. V8 durează 100 ms; Phasis durează 10 s; ambele sunt mult sub timpul de expirare al cererii. Pentru a reduce și mai mult diferența, ar trebui ca JsToPhp să învețe mai multe forme (deducerea tipurilor parametrilor, transformarea `await` / `yield*`) sau să emită direct coduri de operație opcache, în loc să treacă prin `eval()`. Consultați [Benchmarkuri § Foaie de parcurs](https://phasis.inline0.dev/ro/docs/advanced/benchmarks#roadmap).

## Concurență multi-agent

Modelul `SharedArrayBuffer` + `Atomics.wait` + `postMessage` al JavaScript presupune că gazda poate rula fire de execuție OS reale. PHP nu poate (fără `pcntl_fork`, care nu este disponibil peste tot).

Phasis simulează un singur agent — `Atomics.wait` returnează imediat „not-equal” sau „timed-out”, iar `notify` returnează întotdeauna 0. Astfel trece toate testele test262 care rulează cu un singur agent (validarea intrărilor, căile de eroare, notificarea fără acțiune), care reprezintă 376 din testele Atomics 376.

Testele care necesită ca doi agenți concurenți să se observe reciproc nu sunt acceptate. Pentru paralelism real, folosiți o coadă de lucrători la nivelul PHP (Redis, Beanstalkd, …).

## Semantica realm-urilor

`ShadowRealm` este implementat, dar fiecare realm copil rulează în același proces PHP cu gazda. Funcțiile gazdei pot scăpa referințe între realm-uri dacă nu aveți grijă să izolați codul PHP. Specificația permite acest lucru; V8 impune o izolare mai strictă prin instanțe separate v8::Isolate.

`createRealm()` (cârlig pentru gazda test262) creează intern un `Phasis\Engine` nou și face legătura cu biblioteca standard.

## Alegerea motorului pentru expresii regulate

Phasis folosește PCRE2 din PHP ca motor principal pentru expresii regulate, cu un matcher personalizat pentru cazurile pe care PCRE2 nu le poate gestiona exact (lookbehind cu capturi, grupuri cuantificate cu resetare, semantica anumitor opțiuni `/v`). Matcherul personalizat este mai lent decât PCRE2 și este folosit doar când distribuirea detectează un tipar incompatibil.

Consecința notabilă: tabelul de conversie la litere mici/majuscule din PCRE2 poate diferi de cel al versiunii ICU din V8, mai ales pe distribuțiile Linux mai vechi (Ubuntu 22.04 include ICU 70; Phasis include un tabel de conversie ICU 76+ pentru a compensa diferențele gazdei la tiparele `/iu`).

## Modelul de memorie

Colectorul de gunoi cu numărarea referințelor din PHP diferă de colectorul cu urmărire din V8. Obiectele PHP capturate de închiderile gazdei rămân active cât timp motorul păstrează acele închideri, iar ciclurile dintre ele nu sunt colectate până când `Engine` este distrus. Folosiți `WeakMap` / `WeakRef` pentru cache-urile pe care nu doriți să le mențineți active.

API-urile de introspecție specifice V8, precum `process.memoryUsage()`, nu sunt implementate.

## Încărcătorul de module

Încărcătorul de module ES rezolvă importurile relative în raport cu sistemul de fișiere, dar nu înțelege convențiile instrumentelor de împachetare:

- Fără rezolvare `node_modules`.
- Fără maparea `package.json` `exports`.
- Fără deducerea extensiei fișierului (trebuie să scrieți `import './foo.mjs'`, nu `import './foo'`).
- Fără importuri HTTP.

Aceasta corespunde specificației ECMAScript de bază, dar nu comportamentului Node. Nu există niciun cârlig pentru un rezolvator de module personalizat. Pentru a folosi pachete npm, împachetați-le cu un instrument precum esbuild într-un singur script sau modul înainte de a-l transmite către Phasis.

## Wasm

`WebAssembly` nu este implementat. Nu există un runtime wasm PHP de conectat.

## API-uri web disponibile doar în browser, pe care le omitem

Phasis include întregul **Web Platform Pack** (`URL`, `TextEncoder`/`TextDecoder`, `atob`/`btoa`, `structuredClone`, `performance`, `DOMException`), întregul **Fetch Pack** (`fetch`, `Request`, `Response`, `Headers`, `Body`, `AbortController`/`AbortSignal`, `Blob`/`File`, `FormData`, `EventTarget`/`Event`, WHATWG Streams complet, `navigator`), plus `crypto` (`getRandomValues`, `randomUUID`, `SubtleCrypto` complet: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), `WebSocket` (constructor + codec pentru cadre RFC 6455, transport interschimbabil), `XMLHttpRequest` (stratificat peste transportul fetch) și o buclă de evenimente reală (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `queueMicrotask`, `AsyncContext`). Consultați [API-uri web](https://phasis.inline0.dev/ro/docs/compatibility/web-apis).

Ce *nu* este inclus:

- `window`, `document`, arborele DOM — Phasis nu este un browser.
- `localStorage`, `sessionStorage`, `IndexedDB` — aspecte care țin de gazdă; aplicația integratoare gestionează persistența.
- `Worker`, `SharedWorker`, `MessageChannel` — necesită fire de execuție OS reale, pe care PHP nu le oferă.
- Service Workers, Push API, Notifications, BroadcastChannel — fără relevanță în afara unui browser.

## Variabile globale Node

`process`, `Buffer`, `__dirname`, `__filename`, `require()` — niciuna dintre acestea nu există. Sunt convenții ale gazdei Node, nu funcționalități ale limbajului.

Dacă portați cod Node, înlocuiți `require('foo')` cu `import 'foo'`, înlocuiți `process.env.X` cu un `env.X` legat de gazdă și transmiteți căi echivalente cu `__dirname` din PHP.

## Precizie zecimală

Numerele ECMAScript sunt valori double IEEE 754. Aritmetica zecimală cu mai mult de 15 cifre semnificative pierde precizia exact ca în orice alt motor JS. Folosiți `BigInt` pentru calcule exacte cu numere întregi sau o bibliotecă zecimală JS dacă aveți nevoie de calcule exacte cu fracții.

`bcmath` din PHP este folosit intern pentru `BigInt`; singura diferență reală față de V8 este că operațiile bigint foarte mari sunt mai lente în PHP decât în implementarea C++ a V8. Corectitudinea numerică este identică.
