Kända begränsningar
Phasis strävar efter att bete sig identiskt med V8 i alla observerbara specifikationstester. Den här sidan beskriver var identiteten upphör i praktiken — vanligtvis på grund av grundläggande skillnader mellan en PHP-tolk som går igenom trädet och en JIT-kompilerad C++-motor.
Prestandatak
Motorn går igenom syntaxträdet med en opportunistisk bytekod-VM och en JsToPhp-transpilerare som sänker numeriktunga kroppar och kroppar med många lokala variabler (inklusive formerna obj.method(), new Ctor() och this.member) till inbyggda PHP-closures som PHP 8.5:s spårande JIT kan kompilera till maskinkod. Större delen av den aktiva exekveringen sker i VM:ens switch-loop eller direkt i JIT-kompilerad PHP — inte genom att syntaxträdet gås igenom — men varje VM-opkod medför fortfarande en dispatchkostnad för PHP, och former som JsToPhp ännu inte hanterar faller tillbaka till den långsammare VM:en. Taket för arbetsbelastningar som begränsas av dispatch är ungefär ~100× långsammare än V8.
För inbäddningsfall — att köra användartillhandahållen logik på PHP-data, innehållsomvandlingspipelines och valideringsregler — spelar taket sällan någon roll. V8 är 100 ms; Phasis är 10 s; båda ligger långt under tidsgränsen för begäran. För att minska återstående skillnad behöver JsToPhp lära sig fler former (inferens av parametertyper, sänkning av await / yield*) eller generera opkoder för opcache direkt i stället för via eval(). Se Benchmarks § Roadmap.
Samtidighet mellan flera agenter
JavaScripts modell med SharedArrayBuffer + Atomics.wait + postMessage förutsätter att värden kan köra riktiga OS-trådar. PHP kan inte det utan pcntl_fork, som inte finns på alla värdar.
Phasis simulerar en enda agent — Atomics.wait returnerar omedelbart "not-equal" eller "timed-out", och notify returnerar alltid 0. Det klarar alla test262-tester som körs med en enda agent (indatavalidering, felvägar, no-op notify), vilket omfattar 376 av 376-testerna för Atomics.
Tester som faktiskt kräver att två samtidiga agenter observerar varandra stöds inte. Använd en arbetskö på PHP-nivå (Redis, Beanstalkd, …) för verklig parallellism.
Realm-semantik
ShadowRealm är implementerat, men varje underordnad realm körs i samma PHP-process som värden. Värdfunktioner kan läcka referenser mellan realms om du inte är noga med att hålla PHP-kod isolerad. Specifikationen tillåter detta; V8 upprätthåller striktare isolering genom separata v8::Isolate-instanser.
createRealm() (test262-hook för värdmiljön) skapar en ny Phasis\Engine internt och kopplar standardbiblioteket över.
Val av regexmotor
Phasis använder PCRE2 från PHP som primär regexbackend och en anpassad matchare för fall som PCRE2 inte kan hantera exakt (lookbehind med captures, kvantifierade grupper med reset, vissa semantiker för flaggan /v). Den anpassade matcharen är långsammare än PCRE2 och används bara när dispatch upptäcker ett inkompatibelt mönster.
En märkbar följd är att PCRE2 kan ha en annan tabell för skiftlägesvikning än ICU-versionen i V8, särskilt i äldre Linux-distributioner (Ubuntu 22.04 levereras med ICU 70; Phasis paketerar en ICU 76+-tabell för skiftlägesvikning som åsidosätter skillnader i värdmiljön för /iu-mönster).
Minnesmodell
PHPs referensräknande GC skiljer sig från den spårande insamlaren i V8. PHP-objekt som fångas av closures i värdmiljön hålls vid liv så länge motorn behåller dessa closures, och cykler mellan dem samlas inte in förrän Engine förstörs. Använd WeakMap / WeakRef för cachar som du inte vill hålla vid liv.
process.memoryUsage() och liknande introspektions-API:er som är specifika för V8 är inte implementerade.
Modulhanterare
ES-modulhanteraren löser relativa importer mot filsystemet men förstår inte bundlarens konventioner:
- Ingen
node_modules-upplösning. - Ingen
package.json-karta förexports. - Ingen inferens av filändelser (du måste skriva
import './foo.mjs', inteimport './foo'). - Inga HTTP-importer.
Detta följer den rena ECMAScript-specifikationen men inte Nodes beteende. Det finns ingen hook för en anpassad modulresolver. Om du vill använda npm-paket paketerar du dem till ett enda skript eller en enda modul med ett verktyg som esbuild innan du skickar dem till Phasis.
Wasm
WebAssembly är inte implementerat. Det finns ingen PHP-körtid för wasm att koppla till.
Web-API:er som bara finns i webbläsare och som vi utelämnar
Phasis innehåller hela Web Platform Pack (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), hela Fetch Pack (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, hela WHATWG Streams och navigator), samt crypto (getRandomValues, randomUUID, hela SubtleCrypto: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (konstruktor + RFC 6455-ramkodare, utbytbart transportlager), XMLHttpRequest (byggt ovanpå fetch-transporten) och en riktig händelseslinga (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Se Webb-API:er.
Det här ingår inte:
window,documentoch DOM-trädet — Phasis är ingen webbläsare.localStorage,sessionStorage,IndexedDB— ansvar som ligger hos värdmiljön; den som bäddar in hanterar beständig lagring.Worker,SharedWorker,MessageChannel— kräver riktiga OS-trådar, vilket PHP inte erbjuder.- Service Workers, Push API, aviseringar och BroadcastChannel — irrelevanta utanför en webbläsare.
Globala objekt i Node
process, Buffer, __dirname, __filename, require() — inget av detta finns heller. Det är konventioner för Nodes värdmiljö, inte språkfunktioner.
Om du portar Node-kod ersätter du require('foo') med import 'foo', byter ut process.env.X mot en värdbunden env.X och skickar in sökvägar som motsvarar __dirname från PHP.
Decimalprecision
ECMAScript-tal är IEEE 754-dubbelprecisionstal. Decimala beräkningar med fler än 15 signifikanta siffror tappar precision precis som i alla andra JS-motorer. Använd BigInt för exakt heltalsmatematik eller ett decimalt bibliotek för JS om du behöver exakta bråktalsberäkningar.
PHPs bcmath används internt för BigInt; den enda faktiska skillnaden mot V8 är att mycket stora bigint-operationer är långsammare i PHP än i V8s C++-implementation. Den numeriska korrektheten är densamma.