انتقل إلى المحتوى

Phasis

محرك JavaScript مكتوب بلغة PHP: يحقق اجتياز جميع اختبارات test262 البالغ عددها 50,506 لدعم ES2024+ (لقطة 2025-05-05)، إضافة إلى URL والترميز وstructuredClone وfetch وStreams.

الطرفية
composer require phasis/phasis

أحدث إصدار v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

في التطبيق العملي

يشغّل كائن المحرك الواحد JavaScript داخل عملية PHP ويمرر القيم في الاتجاهين.

شغّل JavaScript من PHP

يقيّم Phasis\Engine السلاسل والملفات المصدرية داخل عملية PHP التي تستدعيه. يحوّل setGlobal() مصفوفات PHP إلى مصفوفات وكائنات JavaScript، ويلتف حول إغلاقات PHP ليعرضها كدوال.

تُخزّن مخرجات console.log مؤقتًا في المحرك وتُقرأ مجددًا باستخدام getConsoleOutput(). لا يحتاج المنسّق في علامة التبويب الثانية إلى محرك إطلاقًا.

المحرك
use Phasis\Engine;

$engine = new Engine();

// Evaluate an expression
$engine->eval('1 + 2 * 3');                  // 7

// Run a file
$engine->execFile('/path/to/script.js');

// Bridge a PHP value into JS (arrays are copied)
$engine->setGlobal('config', ['debug' => true]);
$engine->eval('config.debug');               // true

// console.log is buffered, not printed
$engine->eval('console.log("hi")');
echo $engine->getConsoleOutput();            // hi

// Expose a PHP closure as a JS function
$engine->setGlobal('greet', fn(string $name) => "Hello, $name");
$engine->eval('greet("world")');             // "Hello, world"

PHP خالص

دون exec() أو FFI أو Node. يتطلب PHP 8.2+ مع ext-curl وext-bcmath وext-mbstring؛ ويشغّل CI الإصدارات PHP 8.4 و8.5.

100% test262

يجتاز الاختبارات الـ 50,506 كلها في مجموعة اختبارات مطابقة ECMAScript وفق لقطة 2025-05-05، في كل الفئات ومن دون تخطّي أي اختبار.

ECMAScript حديث

الفئات وasync/await والمولّدات وSymbol وBigInt وProxy وTemporal وTypedArray وIntl مع ext-intl. دعم كامل لـ ES2024+.

واجهات برمجة منصة الويب

تتوفر URL وTextEncoder وTextDecoder وatob وbtoa وstructuredClone وperformance وDOMException مدمجة.

fetch + التدفقات

اتصالات HTTP حقيقية من JS عبر ext-curl. دعم كامل لـ Fetch API مع AbortSignal وBlob وFormData وWHATWG Streams.

اختبارات منصة الويب

تجتاز الاختبارات الفرعية المستوردة من WPT لـ fetch وheaders وblob وabort وstreams وencoding، باستثناء قائمة سماح لحالات brotli وSharedArrayBuffer.

التشغيل البيني بين PHP وJS

يتيح setGlobal() استخدام إغلاقات PHP كدوال JS، كما يشغّل call() دوال JS من PHP. تُحوّل القيم عند الحد الفاصل، وتُنسخ المصفوفات.

قابل للتضمين

فئة Engine واحدة: eval وexecFile وsetGlobal وcall. أضفها إلى أي تطبيق PHP أو CLI.

حد مكدس الاستدعاءات

يوقف مكدس استدعاءات ثابت بسعة 4,096 إطارًا التكرار الجامح عبر InternalError يمكن التقاطه.

CLI

يشغّل bin/phasis ملفًا أو مقطع -e ويطبع AST باستخدام --ast. وفي نسخة مستودع، يشغّل bin/test262 مجموعة اختبارات المطابقة.

الأداة المرجعية Node.js

تُتحقق السيناريوهات بمقارنتها مع Node.js (V8). تُشغّل اختبارات WPT ومجموعة المكتبة في CI عند دفع تغييرات تمس المحرك؛ أما اجتياز test262 كاملًا فيُشغّل عند الطلب، وكان آخر تشغيل في 2026-06-09.

مكتبات حقيقية

تُختبر 204 حزمة npm، منها acorn وmustache.js وlodash وmarked، مع تطابق المخرجات بايتًا ببايت مع Node.

لماذا Phasis؟

لا توجد عملية Node.js

يحلّل Phasis المعجم ويحلّل وينفّذ JavaScript بنفسه في PHP، من دون استدعاء exec() إلى Node أو FFI. ويُثبّت كحزمة Composer.

التحكم المضيف في fetch

يستخدم fetch() ext-curl افتراضيًا. يبدّل setFetchTransport() وسيلة النقل، مثلًا بمحاكاة في الاختبارات، ويمكن لـ setFetchPolicy() رفض كل طلب أو إعادة كتابته قبل إرساله.

المؤقتات وفق وقت افتراضي

يفرّغ eval() حلقة الأحداث قبل أن يعود، وتقفز الساعة إلى المؤقت المعلّق التالي بدلًا من الانتظار. ويمكن للمضيفات طويلة العمر تشغيل الحلقة بالوقت الفعلي باستخدام tickEventLoop().

يتضمن محللًا ومنسّقًا

يعيد المحلل شجرة AST مكتوبة الأنواع من PHP ويصدرها بصيغة ESTree. ويعيد المنسّق طباعة JavaScript وJSON وCSS بتنسيق متوافق مع prettier.

مقارنة مع

طرق أخرى لتشغيل JavaScript أو معالجته من تطبيق PHP.

Phasis مقارنةً بأدوات أخرى
Node.js مناسب لـيشغّل Node.js JavaScript على محرك V8 ويحل الحزم من مجلدات node_modules، لذا تُحمّل تبعيات npm بالاسم. الاختلاف عن Phasisيضيف استدعاء Node من PHP بيئة تشغيل ثانية وحدًا فاصلًا بين العمليات. يعمل Phasis داخل PHP، لكن محمّل وحداته لا يدعم مجلدات node_modules أو حل صادرات package.json، لذا يجب تجميع حزم npm أولًا، مثلًا باستخدام esbuild.
V8Js مناسب لـتضمّن V8Js محرك V8 من Google في PHP وتشغّل JavaScript داخل صندوق عزل يمكن تقييده بحد زمني وحد للذاكرة. الاختلاف عن PhasisV8Js إضافة مجمّعة تتطلب مكتبة libv8. أما Phasis فهي PHP خالصة من Composer، وتشير وثائقها إلى أن وقت تشغيلها يبلغ نحو 100 ضعف وقت V8 في الشيفرات التي يهيمن عليها التوزيع.
Peast مناسب لـيحلّل Peast شيفرة JavaScript إلى شجرة AST بصيغة ESTree على PHP 5.4 وما بعده، ويضيف التنقل في الشجرة واستعلامات المحددات والعرض. الاختلاف عن Phasisيتطلب Phasis الإصدار PHP 8.2. يعيد محلله كائنات عقد مكتوبة الأنواع وللقراءة فقط مع تصدير ESTree، ويمكن للحزمة نفسها أيضًا تنفيذ الشيفرة.
Prettier مناسب لـينسّق Prettier شيفرات JavaScript وTypeScript وJSX وCSS وHTML وMarkdown وYAML وغيرها، ويمكن تثبيته من npm. الاختلاف عن Phasisيغطي منسّق Phasis JavaScript وJSON وCSS فقط. تطابق خياراته prettier 3.x ويعمل في PHP من دون Node.js.

الأسئلة والأجوبة

إجابات موجزة من توثيق Phasis.

ابدأ بدليل البدء، ثم اقرأ مرجع API الخاص بخطافات fetch وحلقة الأحداث.