Γνωστοί περιορισμοί
Το Phasis επιδιώκει να συμπεριφέρεται πανομοιότυπα με το V8 σε κάθε παρατηρήσιμη δοκιμή προδιαγραφών. Αυτή η σελίδα περιγράφει τα σημεία όπου στην πράξη παύει να ισχύει αυτή η ταυτότητα — συνήθως λόγω θεμελιωδών διαφορών ανάμεσα σε έναν διερμηνέα PHP που διασχίζει το δέντρο και μια μηχανή C++ που μεταγλωττίζει με JIT.
Όριο επιδόσεων
Η μηχανή διασχίζει το δέντρο, διαθέτει VM bytecode που ενεργοποιείται ευκαιριακά και transpiler JsToPhp που μετατρέπει σώματα με έμφαση στους αριθμούς / στα τοπικά στοιχεία (συμπεριλαμβανομένων των σχημάτων obj.method(), new Ctor() και this.member) σε εγγενή closures PHP, τα οποία το tracing JIT της έκδοσης 8.5 του PHP μπορεί να μεταγλωττίσει σε κώδικα μηχανής. Το μεγαλύτερο μέρος της θερμής αποστολής εντολών γίνεται μέσα στον βρόχο switch της VM ή απευθείας σε κώδικα PHP που έχει μεταγλωττιστεί με JIT — όχι με διάσχιση του AST — αλλά κάθε opcode της VM εξακολουθεί να επιβαρύνεται με το κόστος αποστολής PHP, ενώ κάθε σχήμα που δεν υποστηρίζει ακόμη το JsToPhp επιστρέφει στην πιο αργή VM. Το ανώτατο όριο σε φόρτους εργασίας που περιορίζονται από την αποστολή εντολών είναι περίπου 100× πιο αργό από το V8.
Για φόρτους εργασίας ενσωμάτωσης — εκτέλεση λογικής που παρέχεται από τον χρήστη πάνω σε δεδομένα PHP, αγωγούς μετασχηματισμού περιεχομένου, κανόνες επικύρωσης — το όριο σπάνια έχει σημασία. Το V8 διαρκεί 100 ms· το Phasis διαρκεί 10 s· και οι δύο χρόνοι είναι πολύ κάτω από το χρονικό όριο του αιτήματος. Για να καλυφθεί μεγαλύτερο μέρος της διαφοράς, θα έπρεπε να προστεθούν περισσότερα σχήματα στο JsToPhp (συμπέρασμα τύπου παραμέτρων, μετατροπή await / yield*) ή να παράγονται απευθείας opcodes του opcache αντί μέσω του eval(). Δείτε Συγκριτικές δοκιμές § Οδικός χάρτης.
Ταυτόχρονη εκτέλεση πολλών agent
Το μοντέλο SharedArrayBuffer + Atomics.wait + postMessage του JavaScript προϋποθέτει ότι το περιβάλλον υποδοχής μπορεί να εκτελεί πραγματικά νήματα λειτουργικού συστήματος. Το PHP δεν μπορεί (χωρίς pcntl_fork, που δεν είναι διαθέσιμο σε κάθε περιβάλλον υποδοχής).
Το Phasis προσομοιώνει έναν μόνο agent — το Atomics.wait επιστρέφει αμέσως "not-equal" ή "timed-out", ενώ το notify επιστρέφει πάντα 0. Έτσι περνούν όλες οι δοκιμές test262 που εκτελούνται με έναν agent (επικύρωση εισόδου, διαδρομές σφαλμάτων, ειδοποίηση χωρίς ενέργεια), οι οποίες καλύπτουν 376 από τις δοκιμές Atomics 376.
Δεν υποστηρίζονται δοκιμές που απαιτούν πραγματικά δύο ταυτόχρονους agent να παρατηρούν ο ένας τον άλλον. Για πραγματικό παραλληλισμό, χρησιμοποιήστε ουρά worker στο επίπεδο PHP (Redis, Beanstalkd, …).
Σημασιολογία realm
Το ShadowRealm υλοποιείται, αλλά κάθε θυγατρικό realm εκτελείται στην ίδια διεργασία PHP με το περιβάλλον υποδοχής. Οι συναρτήσεις του περιβάλλοντος υποδοχής μπορούν να διαρρεύσουν αναφορές μεταξύ realm, αν δεν φροντίσετε να απομονώσετε τον κώδικα PHP. Αυτό επιτρέπεται από την προδιαγραφή· το V8 επιβάλλει αυστηρότερη απομόνωση μέσω ξεχωριστών στιγμιοτύπων v8::Isolate.
Το createRealm() (hook περιβάλλοντος υποδοχής του test262) δημιουργεί εσωτερικά ένα νέο Phasis\Engine και γεφυρώνει την τυπική βιβλιοθήκη.
Επιλογή μηχανής regex
Το Phasis χρησιμοποιεί το PCRE2 του PHP ως κύριο backend regex, μαζί με προσαρμοσμένο matcher για περιπτώσεις που το PCRE2 δεν μπορεί να χειριστεί ακριβώς (lookbehind με captures, ποσοτικοποιημένες ομάδες με reset, ορισμένη σημασιολογία των σημαιών /v). Ο προσαρμοσμένος matcher είναι πιο αργός από το PCRE2 και χρησιμοποιείται μόνο όταν η αποστολή εντολών εντοπίσει ασύμβατο μοτίβο.
Σημαντική συνέπεια: το PCRE2 μπορεί να έχει διαφορετικό πίνακα μετατροπής πεζών/κεφαλαίων από την έκδοση ICU του V8, ιδίως σε παλαιότερες διανομές Linux (το Ubuntu 22.04 παρέχει ICU 70· το Phasis περιλαμβάνει πίνακα μετατροπής πεζών/κεφαλαίων ICU 76+ για να παρακάμπτει τις διαφορές του περιβάλλοντος υποδοχής σε μοτίβα /iu).
Μοντέλο μνήμης
Ο συλλέκτης απορριμμάτων καταμέτρησης αναφορών του PHP διαφέρει από τον ιχνηλατικό συλλέκτη του V8. Τα αντικείμενα PHP που διατηρούνται από closures του περιβάλλοντος υποδοχής παραμένουν ενεργά όσο η μηχανή διατηρεί αυτά τα closures, ενώ οι κύκλοι μεταξύ τους δεν συλλέγονται πριν καταστραφεί το Engine. Χρησιμοποιήστε WeakMap / WeakRef για caches που δεν θέλετε να διατηρούνται ενεργές.
Δεν έχουν υλοποιηθεί τα process.memoryUsage() και παρόμοια API ενδοσκόπησης ειδικά για το V8.
Φόρτωση module
Ο loader ES module επιλύει σχετικές εισαγωγές βάσει του συστήματος αρχείων, αλλά δεν κατανοεί τις συμβάσεις των bundler:
- Δεν υπάρχει επίλυση
node_modules. - Δεν υπάρχει χάρτης
package.jsonexports. - Δεν γίνεται συμπέρασμα επέκτασης αρχείου (πρέπει να γράψετε
import './foo.mjs', όχιimport './foo'). - Δεν υπάρχουν εισαγωγές HTTP.
Αυτό συμφωνεί με την καθαρή προδιαγραφή ECMAScript, αλλά όχι με τη συμπεριφορά του Node. Δεν υπάρχει hook για προσαρμοσμένο module resolver. Για να χρησιμοποιήσετε πακέτα npm, συνδυάστε τα με ένα εργαλείο όπως το esbuild σε ένα script ή module πριν τα δώσετε στο Phasis.
Wasm
Το WebAssembly δεν έχει υλοποιηθεί. Δεν υπάρχει runtime wasm PHP για σύνδεση.
Web API μόνο για προγράμματα περιήγησης που παραλείπουμε
Το Phasis παρέχει ολόκληρο το Web Platform Pack (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), ολόκληρο το Fetch Pack (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, πλήρες WHATWG Streams, navigator), καθώς και crypto (getRandomValues, randomUUID, πλήρες SubtleCrypto: digest, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (constructor + κωδικοποιητής πλαισίων RFC 6455, εναλλάξιμη μεταφορά), XMLHttpRequest (σε επίπεδο πάνω από τη μεταφορά fetch) και πραγματικό event loop (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Δείτε Web API.
Τι δεν παρέχεται:
window,document, το δέντρο DOM — το Phasis δεν είναι πρόγραμμα περιήγησης.localStorage,sessionStorage,IndexedDB— ζητήματα του περιβάλλοντος υποδοχής· ο ενσωματωτής αναλαμβάνει τη διατήρηση δεδομένων.Worker,SharedWorker,MessageChannel— απαιτούν πραγματικά νήματα λειτουργικού συστήματος, τα οποία δεν παρέχει το PHP.- Service Workers, Push API, Notifications, BroadcastChannel — άσχετα εκτός προγράμματος περιήγησης.
Καθολικές μεταβλητές Node
process, Buffer, __dirname, __filename, require() — καμία από αυτές δεν υπάρχει. Είναι συμβάσεις του περιβάλλοντος υποδοχής του Node, όχι χαρακτηριστικά της γλώσσας.
Αν μεταφέρετε κώδικα Node, αντικαταστήστε το require('foo') με το import 'foo', αντικαταστήστε το process.env.X με ένα env.X που παρέχεται από το περιβάλλον υποδοχής και περάστε διαδρομές ισοδύναμες με __dirname από το PHP.
Δεκαδική ακρίβεια
Οι αριθμοί ECMAScript είναι διπλής ακρίβειας IEEE 754. Οι δεκαδικοί υπολογισμοί με περισσότερα από 15 σημαντικά ψηφία χάνουν ακρίβεια, όπως ακριβώς συμβαίνει σε κάθε άλλη μηχανή JS. Για ακριβείς ακέραιους υπολογισμούς, χρησιμοποιήστε BigInt· για ακριβή κλασματικά μαθηματικά, χρησιμοποιήστε μια δεκαδική βιβλιοθήκη JS.
Το bcmath του PHP χρησιμοποιείται εσωτερικά για το BigInt· η μόνη ουσιαστική διαφορά από το V8 είναι ότι οι πολύ μεγάλες πράξεις bigint είναι πιο αργές στο PHP από ό,τι στην υλοποίηση C++ του V8. Η αριθμητική ορθότητα είναι ίδια.