Chrono Mock
اللغةالعربية

تزييف التاريخ في تطبيق Electron

ابحث عن هذا وستجد أن كل إجابة تدور حول تعديل شيفرتك أنت - محاكاة الكائن Date أو استخدام المؤقتات الوهمية في إطار الاختبار. ولا شيء من هذا يفيد حين يكون بين يديك تطبيق مبني فعلًا. وهذه الأداة تشغّل التطبيق الذي لديك أصلًا.

لماذا لا يصل إليه الحقن

وُجد هذا الوضع بسبب إخفاق بعينه. شُغّل مؤقّت بومودورو مبني على Electron بجلسة x60 فلم يتحرك عدّه التنازلي إطلاقًا. وتفكيك حزمة التطبيق كشف سببين مستقلين، ولم يكن لأي منهما حل في الجانب الأصلي:

  • لم يكن العدّ التنازلي يقرأ ساعة. كان عدّادًا تزيده setInterval ويعمل داخل Web Worker. ولم يكن هناك استدعاء للوقت يمكن اعتراضه، لأن التطبيق لم يسأل قط عن الوقت.
  • ويعيش ذلك الـ worker في عملية عرض معزولة، وهو بالضبط الموضع الذي لا تدخله مكتبة محقونة من الخارج.

فالآلية الخاصة بـ Windows لا تفيد هنا، والجواب أن نخاطب محرّك JavaScript الخاص بالتطبيق نفسه.

ما يحدث بدلًا من ذلك

يُشغَّل التطبيق بمنفذ لتصحيح الأخطاء وبملف تعريف نظيف مؤقت، وتوضع واجهات الوقت الخاصة به على ساعة الجلسة عبر بروتوكول DevTools - Date.now والمُنشئ new Date() وperformance.now وsetTimeout وsetInterval.

ويُثبَّت التجاوز في كل سياق يفتحه التطبيق، بما في ذلك الـ Web Workers - وهو الموضع الذي يتبيّن عادةً أن المؤقّت يعيش فيه، والموضع الوحيد الذي ما كان الحقن الأصلي ليصل إليه.

ولا يتغير شيء في طريقة تشغيلك. الأمر نفسه، والنافذة نفسها، ولوحة الجلسة نفسها بالساعتين والحكم.

# الأمر نفسه المستخدم مع التطبيق الأصلي - ويُكتشف الوضع تلقائيًا
chrono run "%LOCALAPPDATA%\Programs\your-app\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60

حدّان يجدر معرفتهما قبل أن تبدأ

التشغيل هنا اقتحامي، ويصرّح بذلك عمدًا.

يُشغَّل التطبيق ومنفذ تصحيح الأخطاء البعيد مفتوح وبملف تعريف جديد معزول تحت %TEMP% - فلا يعمل على ملف تعريفك الحقيقي، وليس هو النسخة الموجودة أصلًا في صينية النظام. ويُحذف ملف التعريف عند انتهاء الجلسة، وإن تعذّر ذلك فملخص الجلسة يقول ذلك بدل تركه بصمت.

وتمرير --user-data-dir أو --remote-debugging-port من عندك يُرفض ولا يُتجاوَز، لأن الحادث البديهي - توجيه الجلسة إلى ملف تعريف متصفحك الحقيقي - لا يستحق أن يُسمح به.

الصفحات تقرأ المنطقة الزمنية للجلسة.

توضع كل صفحة وكل worker على المنطقة الزمنية للجلسة، وهي إزاحة ثابتة بلا توقيت صيفي، وتتحقق من الإزاحة التي تقرؤها، فيُبلَّغ عن أي صفحة قرأت منطقة أخرى. وهناك قيدان: يسمّي Intl تلك المنطقة بإزاحة مثل GMT+02:00 لا باسم مدينة، وتشغّل العملية الرئيسية لتطبيق Electron شيفرة JavaScript داخل Node الذي لا تصل إليه الجلسة، فتحتفظ بالساعة الحقيقية، ويذكر التقرير ذلك.

وثمة أمر آخر يفاجئ الناس: الفاصل الزمني المجدوَل أصلًا يحتفظ بمعدّله القديم عند تغيير السرعة في منتصف الجلسة. فـDate.now وnew Date() وperformance.now تستجيب فورًا، أما setInterval الجاري فلا، وتحذّر الجلسة من ذلك بدل أن تتركك تستنتج أن التغيير لم يفعل شيئًا.

إلى أي مدى اختُبر

تجريبي، ولهذه الكلمة معنى محدد هنا: يعمل على الأهداف التي بُني عليها، ولم يُختبر على نطاق واسع، والتدقيق المدمج هو مرجعك لا هذه الصفحة. وقد جرى التحقق منه يدويًا لا بمجموعة الاختبارات الآلية، على تطبيق Electron حقيقي في Windows بنظام 64 بت.

وتُبلَّغ التغطية لكل سياق JavaScript لا لكل عملية، لأن هذه هي الوحدة الموجودة هنا. والتطبيق الخامل الذي لا يسأل عن الوقت أبدًا يُنتج بصدق غير محدَّد - فهو لم يقرأ ساعة، فلا يمكن ادّعاء شيء عما إذا كان سيرى الساعة الصحيحة. ماذا تعني الأحكام ←

جرّبه