Pereiti prie turinio

Žinomi apribojimai

Phasis siekia visuose stebimuose specifikacijos testuose veikti taip pat kaip V8. Šiame puslapyje išvardytos sritys, kuriose praktiškai šis sutapimas baigiasi — dažniausiai dėl esminių skirtumų tarp medį pereinančio PHP interpretatoriaus ir JIT kompiliuojamo C++ variklio.

Našumo riba

Variklis pereina sintaksės medį, turi sąlyginai naudojamą baitkodo VM ir JsToPhp transpilatorių, kuris skaitines / daug vietinių kintamųjų naudojančias funkcijas (įskaitant obj.method(), new Ctor() ir this.member formas) paverčia įprastomis PHP uždaromis funkcijomis, kurias PHP 8.5 sekimo JIT gali sukompiliuoti į mašininį kodą. Didžioji dalis aktyvių iškvietimų vyksta VM perjungimo cikle arba tiesiogiai JIT sukompiliuotame PHP kode, o ne pereinant AST, tačiau kiekviena VM operacija vis tiek patiria PHP iškvietimų sąnaudų, o bet kuri forma, kurios JsToPhp dar nepalaiko, grąžinama į lėtesnę VM. Iškvietimų ribojamų apkrovų našumo riba yra maždaug 100 kartų lėtesnė nei V8.

Įterpimo apkrovoms — naudotojo logikos vykdymui su PHP duomenimis, turinio transformavimo konvejeriams ir validavimo taisyklėms — ši riba retai svarbi. V8 trunka 100 ms; Phasis — 10 s; abu laikai gerokai trumpesni už užklausos skirtąjį laiką. Norint labiau sumažinti skirtumą, reikėtų išmokyti JsToPhp apdoroti daugiau formų (parametrų tipų išvedimą, await / yield* transformavimą) arba tiesiogiai generuoti opcache opkodus, o ne per eval(). Žr. Etaloniniai testai § Planas.

Kelių agentų lygiagretumas

JavaScript modelyje SharedArrayBuffer + Atomics.wait + postMessage daroma prielaida, kad pagrindinė aplinka gali vykdyti tikras OS gijas. PHP to negali (be pcntl_fork, kuris prieinamas ne visose aplinkose).

Phasis imituoja vieną agentą — Atomics.wait iš karto grąžina „not-equal“ arba „timed-out“, o notify visada grąžina 0. Taip išlaikomi visi test262 testai, kuriems pakanka vieno agento (įvesties validavimas, klaidų keliai, tuščias notify), apimantys 376 iš 376 Atomics testų.

Testai, kuriems reikia, kad du agentai vienu metu stebėtų vienas kitą, nepalaikomi. Tikram lygiagretumui naudokite PHP lygmens darbuotojų eilę (Redis, Beanstalkd, …).

Aplinkų semantika

ShadowRealm įgyvendintas, tačiau kiekviena antrinė aplinka veikia tame pačiame PHP procese kaip pagrindinė. Pagrindinės aplinkos funkcijos gali nutekinti nuorodas tarp aplinkų, jei nepasirūpinsite, kad PHP kodas būtų izoliuotas. Specifikacija tai leidžia; V8 užtikrina griežtesnę izoliaciją, naudodamas atskirus v8::Isolate egzempliorius.

createRealm() (pagrindinės aplinkos test262 kabliukas) viduje sukuria naują Phasis\Engine ir sujungia standartinę biblioteką.

Reguliariųjų išraiškų variklio pasirinkimas

Phasis naudoja PHP PCRE2 kaip pagrindinę reguliariųjų išraiškų posistemę, o atvejams, kurių PCRE2 negali tiksliai apdoroti (užfiksuojančios peržiūros atgal, kartojamos grupės su atstatymu, tam tikra /v vėliavėlių semantika), pasitelkia pasirinktinį atitikmenų ieškiklį. Jis lėtesnis už PCRE2 ir naudojamas tik tada, kai parinkiklis aptinka nesuderinamą šabloną.

Svarbi pasekmė: PCRE2 didžiųjų ir mažųjų raidžių vertimo lentelė gali skirtis nuo V8 ICU versijos, ypač senesniuose Linux platinimuose (Ubuntu 22.04 pateikiamas su ICU 70; Phasis turi ICU 76+ raidžių vertimo lentelę, kuri panaikina aplinkos pokyčių poveikį /iu šablonams).

Atminties modelis

PHP nuorodų skaičiavimu pagrįstas šiukšlių surinkimas skiriasi nuo V8 sekimo surinkimo. PHP objektai, kuriuos užfiksuoja pagrindinės aplinkos uždaros funkcijos, lieka gyvi tol, kol variklis laiko tas funkcijas; ciklai tarp jų nesurenkami, kol nesunaikinamas Engine. Talpykloms, kurių nenorite išlaikyti atmintyje, naudokite WeakMap / WeakRef.

process.memoryUsage() ir panašios tik V8 skirtos introspekcijos API neįgyvendintos.

Modulių įkėliklis

ES modulių įkėliklis išsprendžia santykinius importus pagal failų sistemą, tačiau nesupranta rinktuvų konvencijų:

  • Nėra node_modules sprendimo.
  • Nėra package.json exports atvaizdžio.
  • Nėra failo plėtinio išvedimo (privalote rašyti import './foo.mjs', o ne import './foo').
  • Nėra HTTP importų.

Tai atitinka grynąją ECMAScript specifikaciją, bet ne Node elgseną. Nėra kabliuko pasirinktiniam modulių sprendikliui. Norėdami naudoti npm paketus, supakuokite juos su tokiu įrankiu kaip esbuild į vieną scenarijų arba modulį prieš perduodami jį Phasis.

Wasm

WebAssembly neįgyvendintas. Nėra PHP wasm vykdymo aplinkos, su kuria būtų galima susieti.

Praleidžiamos tik naršyklėse veikiančios žiniatinklio API

Phasis pateikia visą Web Platform Pack (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), visą Fetch Pack (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, visą WHATWG Streams, navigator), taip pat crypto (getRandomValues, randomUUID, visą SubtleCrypto: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (konstruktorius ir RFC 6455 kadrų kodekas, keičiamas transportas), XMLHttpRequest (sukurtas ant fetch transporto) bei tikrą įvykių ciklą (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Žr. žiniatinklio API.

Kas nepateikiama:

  • window, document, DOM medis — Phasis nėra naršyklė.
  • localStorage, sessionStorage, IndexedDB — pagrindinės aplinkos atsakomybė; įterpėjas tvarko išsaugojimą.
  • Worker, SharedWorker, MessageChannel — reikia tikrų OS gijų, kurių PHP neturi.
  • Service Workers, Push API, Notifications, BroadcastChannel — už naršyklės ribų nereikalinga.

Node visuotiniai kintamieji

process, Buffer, __dirname, __filename, require() — nė vieno iš jų taip pat nėra. Tai Node pagrindinės aplinkos konvencijos, o ne kalbos funkcijos.

Jei perkeliate Node kodą, pakeiskite require('foo') į import 'foo', vietoj process.env.X naudokite su pagrindine aplinka susietą env.X, o __dirname atitinkančius kelius perduokite iš PHP.

Dešimtainių skaičių tikslumas

ECMAScript skaičiai yra IEEE 754 dvigubo tikslumo skaičiai. Dešimtainė aritmetika, naudojanti daugiau nei 15 reikšminių skaitmenų, praranda tikslumą lygiai taip pat kaip visuose kituose JS varikliuose. Tiksliems sveikųjų skaičių skaičiavimams naudokite BigInt, o tiksliems trupmeniniams skaičiavimams — dešimtainių skaičių biblioteką, pvz., JS.

PHP bcmath viduje naudojamas BigInt; vienintelis tikras skirtumas nuo V8 yra tas, kad labai didelės bigint operacijos PHP veikia lėčiau nei V8 C++ realizacijoje. Skaičiavimų tikslumas vienodas.