Tunnetut rajoitukset
Phasis pyrkii toimimaan kaikissa havaittavissa olevissa spesifikaatiotesteissä samalla tavalla kuin V8. Tällä sivulla luetellaan kohdat, joissa yhtäläisyys ei käytännössä enää päde — yleensä puuta läpikäyvän PHP-tulkin ja JIT-käännetyn C++-moottorin perustavanlaatuisten erojen vuoksi.
Suorituskyvyn yläraja
Moottori käy puuta läpi, käyttää tilaisuuden mukaan tavukoodia suorittavaa VM:ää ja sisältää JsToPhp-transpilerin, joka muuntaa numeeriset tai paikallisiin muuttujiin painottuvat lohkot (mukaan lukien obj.method()-, new Ctor()- ja this.member-muodot) natiiveiksi PHP-sulkeumiksi, jotka PHP 8.5:n jäljityspohjainen JIT voi kääntää konekoodiksi. Suurin osa kuumien toimintojen suorituksesta tapahtuu VM:n switch-silmukan sisällä tai suoraan JIT-käännetyssä PHP-koodissa — ei AST:tä läpikäymällä — mutta jokaisesta VM-opkoodista maksetaan silti PHP-kutsun kustannus, ja kaikki muodot, joita JsToPhp ei vielä käsittele, siirtyvät hitaampaan VM:ään. Kutsujen suorituskyvyn rajoittamissa kuormissa yläraja on suunnilleen 100× hitaampi kuin V8.
Upotuskäytössä — kun suoritetaan käyttäjän antamaa logiikkaa PHP-datalla, sisältömuunnosputkia tai validointisääntöjä — ylärajalla on harvoin merkitystä. V8 kestää 100 ms; Phasis kestää 10 s; molemmat jäävät selvästi pyynnön aikakatkaisun alle. Kuilun kaventaminen edellyttäisi, että JsToPhp oppii käsittelemään lisää muotoja (parametrien tyyppipäätelmät, await- ja yield*-muotojen muunnos) tai että opcache-opkoodit tuotettaisiin suoraan eikä eval()n kautta. Katso Vertailumittaukset § Suunnitelma.
Rinnakkaisuus usean agentin kesken
JavaScriptn SharedArrayBuffer + Atomics.wait + postMessage -malli olettaa, että isäntäympäristö voi suorittaa oikeita käyttöjärjestelmäsäikeitä. PHP ei pysty siihen ilman pcntl_fork, jota ei ole käytettävissä kaikissa isäntäympäristöissä.
Phasis simuloi yhtä agenttia — Atomics.wait palauttaa heti arvon "not-equal" tai "timed-out", ja notify palauttaa aina arvon 0. Tämä läpäisee kaikki yksittäisellä agentilla suoritettavat test262-testit (syötteen validointi, virhetilanteet ja tyhjä notify-kutsu), jotka kattavat 376 Atomics-testeistä 376.
Testit, jotka edellyttävät kahden samanaikaisen agentin havaitsevan toisensa, eivät ole tuettuja. Käytä PHP-tason työjonon rinnalla (Redis, Beanstalkd, …) aitoa rinnakkaisuutta varten.
Realm-semanttiikka
ShadowRealm on toteutettu, mutta jokainen lapsirealm toimii samassa PHP-prosessissa kuin isäntäympäristö. Isäntäympäristön funktiot voivat vuotaa viitteitä realmien välillä, ellet pidä huolta siitä, että PHP-koodi pysyy eristettynä. Spesifikaatio sallii tämän; V8 valvoo tiukempaa eristystä erillisillä v8::Isolate-instansseilla.
createRealm() (test262-isäntäkytkentä) luo sisäisesti uuden Phasis\Engine-instanssin ja yhdistää standardikirjaston siihen.
Säännöllisten lausekkeiden moottorin valinta
Phasis käyttää PHPn PCRE2:ta ensisijaisena säännöllisten lausekkeiden taustamoottorina sekä mukautettua täsmäytintä tapauksissa, joita PCRE2 ei voi käsitellä täsmälleen oikein (sieppauksia sisältävä lookbehind, nollauksen sisältävät toistetut ryhmät ja tietyt /v-lippujen semantiikat). Mukautettu täsmäytin on PCRE2:ta hitaampi, ja sitä käytetään vain, kun käsittely tunnistaa yhteensopimattoman kuvion.
Huomattava seuraus on, että PCRE2:n kirjainkoon muunnostaulukko voi poiketa V8n ICU-versiosta etenkin vanhemmissa Linux-jakeluversioissa (Ubuntu 22.04 sisältää ICU 70:n; Phasis sisältää ICU 76+:n muunnostaulukon, joka ohittaa isäntäympäristön erot /iu-kuvioissa).
Muistimalli
PHPn viitelaskentaan perustuva roskienkeruu eroaa V8n jäljittävästä kerääjästä. Isäntäympäristön sulkeumien kaappaamat PHP-objektit pysyvät elossa niin kauan kuin moottori pitää kyseiset sulkeumat hallussaan, eikä niiden välisiä syklejä kerätä ennen kuin Engine tuhotaan. Käytä WeakMap- tai WeakRef-rakennetta välimuisteille, joita et halua pitää elossa.
process.memoryUsage()- ja vastaavia V8-kohtaisia introspektio-API:eja ei ole toteutettu.
Moduulien lataaja
ES-moduulien lataaja ratkaisee suhteelliset tuonnit tiedostojärjestelmän perusteella, mutta ei ymmärrä paketoijien käytäntöjä:
- Ei
node_modules-ratkaisua. - Ei
package.jsonnexports-karttaa. - Tiedostopäätettä ei päätellä (sinun on kirjoitettava
import './foo.mjs', eiimport './foo'). - Ei HTTP-tuonteja.
Tämä vastaa paljasta ECMAScript-määritystä mutta ei Noden toimintaa. Mukautetulle moduulien ratkaisijalle ei ole kytkentäpistettä. Jos haluat käyttää npm-paketteja, paketoi ne esimerkiksi esbuild-työkalulla yhdeksi komentosarjaksi tai moduuliksi ennen sen välittämistä Phasislle.
Wasm
WebAssembly ei ole toteutettu. Sidottavaksi ei ole käytettävissä PHP-wasm-ajoympäristöä.
Selaimessa käytettävät Web API:t, joita emme sisällytä
Phasis sisältää koko Web Platform Pack -paketin (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), koko Fetch Pack -paketin (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, täydellisen WHATWG Streams -toteutuksen ja navigatorn) sekä crypton (getRandomValues, randomUUID, täydellisen SubtleCrypton: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocketn (konstruktori ja RFC 6455 -kehysmuunnin, vaihdettava siirtotapa), XMLHttpRequestn (Fetch-siirtotavan päälle rakennettu) sekä todellisen tapahtumasilmukan (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Katso Web API:t.
Mitä pakettiin ei sisälly:
window,documentja DOM-puu — Phasis ei ole selain.localStorage,sessionStoragejaIndexedDB— isäntäympäristön vastuulla; upottaja vastaa pysyvästä tallennuksesta.Worker,SharedWorkerjaMessageChannel— edellyttävät oikeita käyttöjärjestelmäsäikeitä, joita PHP ei tarjoa.- Service Workers, Push API, ilmoitukset ja BroadcastChannel — tarpeettomia selaimen ulkopuolella.
Node-yleismuuttujat
process, Buffer, __dirname, __filename ja require() — näitäkään ei ole. Ne ovat Node-isäntäympäristön käytäntöjä, eivät kielen ominaisuuksia.
Jos siirrät Node-koodia, korvaa require('foo') arvolla import 'foo', vaihda process.env.X isäntäympäristöön sidottuun env.X-arvoon ja välitä __dirname-vastaavat polut PHPsta.
Desimaalitarkkuus
ECMAScriptin luvut ovat IEEE 754 -liukulukuja kaksinkertaisella tarkkuudella. Yli 15 merkitsevän numeron desimaalilaskenta menettää tarkkuutta aivan kuten kaikissa muissakin JS-moottoreissa. Käytä BigInttä täsmälliseen kokonaislukulaskentaan tai JS-desimaalikirjastoa, jos tarvitset tarkkaa murtolukulaskentaa.
PHPn bcmathtä käytetään sisäisesti BigIntn toteutukseen; ainoa todellinen ero V8een verrattuna on se, että erittäin suuret bigint-operaatiot ovat hitaampia PHPssä kuin V8n C++-toteutuksessa. Numeerinen oikeellisuus on sama.