
# القيود المعروفة

يهدف Phasis إلى مطابقة V8 تمامًا في كل اختبار مواصفات يمكن ملاحظته. تسرد هذه الصفحة المواضع التي تنتهي عندها هذه المطابقة عمليًا — وعادةً بسبب اختلافات جوهرية بين مفسّر PHP يتبع بنية الشجرة ومحرك C++ يستخدم التجميع الفوري JIT.

## سقف الأداء

المحرك عبارة عن متتبع للشجرة مع آلة افتراضية للبايت كود تعمل بشكل انتهازي ومحوّل JsToPhp يخفض الأجسام كثيرة الأرقام والمتغيرات المحلية (بما في ذلك أشكال `obj.method()` و`new Ctor()` و`this.member`) إلى إغلاقات PHP أصلية يمكن لـJIT التتبعي في الإصدار 8.5 من PHP ترجمتها إلى شيفرة آلة. تجري معظم عمليات الإرسال الساخنة داخل حلقة التبديل في الآلة الافتراضية أو مباشرةً في PHP المترجمة بـJIT، لا عبر اجتياز شجرة البنية المجردة (AST)، لكن كل تعليمة تشغيل في الآلة الافتراضية تظل تتحمل كلفة إرسال PHP، وأي شكل لا يتعامل معه JsToPhp بعد يعود إلى الآلة الافتراضية الأبطأ. يبلغ الحد الأقصى للأحمال التي يحدها الإرسال نحو **~100× أبطأ من V8**.

في أحمال التضمين — تشغيل منطق يقدمه المستخدم على بيانات PHP، ومسارات تحويل المحتوى، وقواعد التحقق — نادرًا ما يكون الحد الأقصى مهمًا. يستغرق V8 مدة 100 ms، بينما يستغرق Phasis مدة 10 s؛ وكلاهما أقل بكثير من مهلة الطلب. ويتطلب تقليص الفجوة أكثر تعليم JsToPhp مزيدًا من الأشكال (استنتاج أنواع المعاملات، وخفض `await` / `yield*`) أو إصدار تعليمات opcache مباشرةً بدلًا من المرور عبر `eval()`. راجع [المعايير § خارطة الطريق](https://phasis.inline0.dev/ar/docs/advanced/benchmarks#roadmap).

## التزامن متعدد الوكلاء

يفترض نموذج JavaScript المكوّن من `SharedArrayBuffer` + `Atomics.wait` + `postMessage` أن المضيف قادر على تشغيل خيوط نظام تشغيل فعلية. لا يستطيع PHP ذلك (من دون `pcntl_fork`، وهي غير متاحة على كل مضيف).

يحاكي Phasis وكيلًا واحدًا — إذ يعيد `Atomics.wait` فورًا «غير متساوٍ» أو «انتهت المهلة»، بينما يعيد `notify` القيمة 0 دائمًا. يجتاز هذا كل اختبارات test262 التي تعمل على وكيل واحد (التحقق من المدخلات، ومسارات الأخطاء، وإشعار بلا إجراء)، وتشمل 376 من أصل 376 اختبارًا لـAtomics.

الاختبارات التي تتطلب فعليًا وكيلين متزامنين يراقب أحدهما الآخر غير مدعومة. استخدم قائمة انتظار للعمال على مستوى PHP (Redis أو Beanstalkd أو …) لتحقيق التوازي الفعلي.

## دلالات Realm

تم تنفيذ `ShadowRealm`، لكن كل Realm فرعي يعمل في عملية PHP نفسها التي يعمل فيها المضيف. قد تسرّب دوال المضيف مراجع بين الـRealms ما لم تحرص على عزل شيفرة PHP. تسمح المواصفة بذلك؛ أما V8 فيفرض عزلًا أشد باستخدام مثيلات v8::Isolate منفصلة.

ينشئ `createRealm()` (خطاف المضيف لـtest262) كائن `Phasis\Engine` جديدًا داخليًا ويربط المكتبة القياسية عبره.

## اختيار محرك Regex

يستخدم Phasis محرك PCRE2 من PHP بوصفه الخلفية الأساسية للتعابير النمطية، مع مطابِق مخصص للحالات التي لا يستطيع PCRE2 معالجتها بدقة (النظر إلى الخلف مع الالتقاطات، والمجموعات المكمّمة ذات إعادة الضبط، وبعض دلالات أعلام `/v`). المطابِق المخصص أبطأ من PCRE2 ولا يُستخدم إلا عندما يكشف التوجيه عن نمط غير متوافق.

النتيجة الملحوظة: قد يختلف جدول طي حالة الأحرف في PCRE2 عن إصدار ICU الخاص بـV8، خاصةً في توزيعات Linux الأقدم (يتضمن Ubuntu 22.04 الإصدار ICU 70؛ ويضمّن Phasis جدول طي ICU 76+ لتجاوز اختلافات المضيف في أنماط `/iu`).

## نموذج الذاكرة

تختلف آلية جمع القمامة بالعد المرجعي في PHP عن جامع القمامة التتبعي في V8. تظل كائنات PHP التي تلتقطها إغلاقات المضيف حية ما دام المحرك يحتفظ بتلك الإغلاقات، ولا تُجمع الدورات بينها حتى يُدمَّر `Engine`. استخدم `WeakMap` / `WeakRef` لذاكرات التخزين المؤقت التي لا تريد إبقاءها حية.

لم يتم تنفيذ `process.memoryUsage()` وواجهات برمجة التطبيقات الاستكشافية الأخرى الخاصة بـV8.

## محمّل الوحدات

يحلّ محمّل وحدات ES الاستيرادات النسبية بالرجوع إلى نظام الملفات، لكنه لا يفهم اصطلاحات أدوات التجميع:

- لا يوجد حلّ لـ`node_modules`.
- لا توجد خريطة `package.json` `exports`.
- لا يوجد استنتاج لامتداد الملف (يجب كتابة `import './foo.mjs'`، لا `import './foo'`).
- لا توجد استيرادات HTTP.

يتوافق هذا مع مواصفة ECMAScript الأساسية، لكنه لا يتوافق مع سلوك Node. لا توجد نقطة ربط لمحلّل وحدات مخصص. لاستخدام حزم npm، اجمعها باستخدام أداة مثل esbuild في سكربت أو وحدة واحدة قبل تمريرها إلى Phasis.

## Wasm

لم يتم تنفيذ `WebAssembly`. لا يوجد وقت تشغيل wasm من PHP للربط به.

## واجهات Web API الخاصة بالمتصفح التي نتجاوزها

يأتي Phasis مع **حزمة منصة الويب** كاملة (`URL`، `TextEncoder`/`TextDecoder`، `atob`/`btoa`، `structuredClone`، `performance`، `DOMException`)، و**حزمة Fetch** كاملة (`fetch`، `Request`، `Response`، `Headers`، `Body`، `AbortController`/`AbortSignal`، `Blob`/`File`، `FormData`، `EventTarget`/`Event`، وتدفقات WHATWG كاملة، و`navigator`)، بالإضافة إلى `crypto` (`getRandomValues`، `randomUUID`، و`SubtleCrypto` كامل: digest وHMAC وAES-GCM/CBC/CTR وRSA-OAEP/PSS/PKCS1 وECDSA وECDH وHKDF وPBKDF2)، و`WebSocket` (منشئ + مرمّز إطارات RFC 6455 مع إمكانية استبدال وسيلة النقل)، و`XMLHttpRequest` (مبني فوق وسيلة نقل fetch)، وحلقة أحداث فعلية (`setTimeout`، `setInterval`، `clearTimeout`، `clearInterval`، `queueMicrotask`، `AsyncContext`). راجع [واجهات Web API](https://phasis.inline0.dev/ar/docs/compatibility/web-apis).

ما لا يتضمنه الإصدار:

- `window` و`document` وشجرة DOM — فـPhasis ليس متصفحًا.
- `localStorage` و`sessionStorage` و`IndexedDB` — هذه أمور تخص المضيف؛ والمضمِّن مسؤول عن الاستمرارية.
- `Worker` و`SharedWorker` و`MessageChannel` — تتطلب خيوط نظام تشغيل فعلية، وهي غير متاحة في PHP.
- Service Workers وPush API والإشعارات و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 منها في تنفيذ V8 بلغة C++. الدقة العددية متطابقة.
