Kendte begrænsninger
Phasis sigter mod at opføre sig identisk med V8 i alle observerbare specifikationstests. Denne side beskriver, hvor denne identitet i praksis ophører — typisk på grund af grundlæggende forskelle mellem en trævandret PHP-fortolker og en JIT-kompileret C++-motor.
Ydeevneloft
Motoren er en trævandrer med en opportunistisk bytecode-VM og en JsToPhp-transpiler, der omsætter numerisk kode og kode med mange lokale variabler (herunder formerne obj.method(), new Ctor() og this.member) til native PHP-closures, som tracing-JIT'en i PHP 8.5 kan kompilere til maskinkode. Det meste varm dispatch foregår i VM'ens switch-løkke eller direkte i JIT-kompileret PHP — ikke ved at gennemløbe AST'et — men hver VM-opkode koster stadig en PHP-dispatchomkostning, og former, som JsToPhp endnu ikke håndterer, falder tilbage til den langsommere VM. Loftet for dispatchbegrænsede arbejdsbelastninger er cirka ~100× langsommere end V8.
For indlejringsarbejdsbelastninger — kørsel af brugerleveret logik på PHP-data, indholdstransformationspipelines og valideringsregler — har loftet sjældent betydning. V8 tager 100 ms; Phasis tager 10 s; begge dele ligger langt under anmodningens timeout. Hvis afstanden skal mindskes yderligere, kræver det, at JsToPhp lærer flere former (inferens af parametertyper, omsætning af await / yield*) eller udsender opcodes til opcache direkte i stedet for via eval(). Se Benchmarks § Roadmap.
Samtidighed mellem flere agenter
JavaScripts model med SharedArrayBuffer + Atomics.wait + postMessage forudsætter, at værten kan køre rigtige OS-tråde. Det kan PHP ikke (uden pcntl_fork, som ikke er tilgængelig på alle værter).
Phasis simulerer én agent — Atomics.wait returnerer straks "not-equal" eller "timed-out", og notify returnerer altid 0. Det består alle test262-tests, der kører med én agent (inputvalidering, fejlforløb, no-op notify), hvilket dækker 376 af 376 Atomics-tests.
Tests, der kræver, at to samtidige agenter observerer hinanden, understøttes ikke. Brug en worker-kø på PHP-niveau (Redis, Beanstalkd, …) for ægte parallelisme.
Realm-semantik
ShadowRealm er implementeret, men hvert child realm kører i samme PHP-proces som værten. Værtsfunktioner kan lække referencer på tværs af realms, medmindre du sørger for at holde PHP-kode isoleret. Specifikationen tillader dette; V8 håndhæver strengere isolation via separate v8::Isolate-instanser.
createRealm() (test262-værtskrog) opretter internt en ny Phasis\Engine og bygger bro mellem standardbibliotekerne.
Valg af regex-motor
Phasis bruger PHPs PCRE2 som primær regex-backend med en tilpasset matcher til tilfælde, som PCRE2 ikke kan håndtere præcist (lookbehind med captures, kvantificerede grupper med nulstilling, visse semantikker for /v-flag). Den tilpassede matcher er langsommere end PCRE2 og bruges kun, når dispatch registrerer et inkompatibelt mønster.
Den bemærkelsesværdige konsekvens: PCRE2 kan have en anden case-folding-tabel end V8s ICU-version, især på ældre Linux-distributioner (Ubuntu 22.04 leveres med ICU 70; Phasis medfølger en ICU 76+-foldingstabel, der tilsidesætter forskelle på værtsystemet for /iu-mønstre).
Hukommelsesmodel
PHPs referenceoptællende GC adskiller sig fra V8s sporende garbage collector. PHP-objekter, der indfanges af værtslukninger, forbliver i live, så længe motoren holder fast i disse lukninger, og cyklusser mellem dem indsamles ikke, før Engine destrueres. Brug WeakMap / WeakRef til caches, du ikke vil holde i live.
process.memoryUsage() og lignende introspektions-API'er, der er specifikke for V8, er ikke implementeret.
Modulindlæser
ES-modulindlæseren løser relative imports i forhold til filsystemet, men forstår ikke bundlerkonventioner:
- Ingen løsning af
node_modules. - Intet
package.json-exports-kort. - Ingen automatisk udledning af filtypenavn (du skal skrive
import './foo.mjs', ikkeimport './foo'). - Ingen HTTP-imports.
Det svarer til den rene ECMAScript-specifikation, men ikke til Nodes adfærd. Der findes intet hook til en brugerdefineret modulresolver. Hvis du vil bruge npm-pakker, skal du bundle dem med et værktøj som esbuild til ét script eller modul, før du giver det videre til Phasis.
Wasm
WebAssembly er ikke implementeret. Der findes ingen PHP-wasm-runtime at binde til.
Web-API'er, der kun findes i browsere, og som vi udelader
Phasis leveres med den fulde Web Platform Pack (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), den fulde Fetch Pack (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, fuld WHATWG Streams, navigator), samt crypto (getRandomValues, randomUUID, fuld SubtleCrypto: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (constructor + RFC 6455 frame-codec, udskiftelig transport), XMLHttpRequest (bygget oven på fetch-transporten) og en ægte event loop (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Se Web-API'er.
Dette følger ikke med:
window,document, DOM-træet — Phasis er ikke en browser.localStorage,sessionStorage,IndexedDB— forhold på værtsiden; embedderen står for persistens.Worker,SharedWorker,MessageChannel— kræver ægte OS-tråde, som PHP ikke tilbyder.- Service Workers, Push API, Notifications, BroadcastChannel — irrelevante uden for en browser.
Node-globale variabler
process, Buffer, __dirname, __filename, require() — ingen af dem findes heller. De er Node-værtskonventioner, ikke sprogegenskaber.
Hvis du porter Node-kode, skal du erstatte require('foo') med import 'foo', udskifte process.env.X med en env.X, der er knyttet til værten, og sende stier svarende til __dirname ind fra PHP.
Decimalpræcision
ECMAScript-tal er IEEE 754-doubles. Decimale beregninger med mere end 15 betydende cifre mister præcision, præcis som i enhver anden JS-motor. Brug BigInt til præcis heltalsregning, eller brug et JS-decimalt bibliotek, hvis du har brug for præcise brøkberegninger.
PHPs bcmath bruges internt til BigInt; den eneste reelle forskel i forhold til V8 er, at meget store bigint-operationer er langsommere i PHP end i V8s C++-implementering. Den numeriske korrekthed er identisk.