Gå til indhold

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', ikke import './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.