Siirry sisältöön

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.jsonn exports-karttaa.
  • Tiedostopäätettä ei päätellä (sinun on kirjoitettava import './foo.mjs', ei import './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, document ja DOM-puu — Phasis ei ole selain.
  • localStorage, sessionStorage ja IndexedDB — isäntäympäristön vastuulla; upottaja vastaa pysyvästä tallennuksesta.
  • Worker, SharedWorker ja MessageChannel — 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.