إعادة هيكلة تقييم المتصفح باستخدام CDP
السياق
act:evaluate ينفذ JavaScript المقدم من المستخدم في الصفحة. حاليًا يعمل عبر Playwright (page.evaluate أو locator.evaluate). يقوم Playwright بتسلسل أوامر CDP لكل صفحة، لذا فإن تقييماً عالقاً أو طويل الأمد يمكن أن يعطل قائمة انتظار أوامر الصفحة ويجعل كل إجراء لاحق على تلك اللسان يبدو "عالقاً". PR #13498 يضيف شبكة أمان عملية (تقييم محدود، نشر الإلغاء، واسترداد بأفضل جهد). يصف هذا المستند إعادة هيكلة أكبر تجعل act:evaluate معزولاً بشكل أساسي عن Playwright بحيث لا يمكن لتقييم عالق أن يعطل عمليات Playwright العادية.
الأهداف
- لا يمكن لـ
act:evaluateأن يعطل بشكل دائم إجراءات المتصفح اللاحقة على نفس اللسان. - المهلات الزمنية هي مصدر وحيد للحقيقة من البداية إلى النهاية بحيث يمكن للمستدعي الاعتماد على ميزانية زمنية.
- يتم التعامل مع الإلغاء والمهلة الزمنية بنفس الطريقة عبر HTTP والإرسال داخل العملية.
- دعم استهداف العناصر للتقييم دون تحويل كل شيء بعيداً عن Playwright.
- الحفاظ على التوافق مع الإصدارات السابقة للمستدعين الحاليين وحمولات البيانات.
غير الأهداف
- استبدال جميع إجراءات المتصفح (نقر، كتابة، انتظار، إلخ) بتنفيذات CDP.
- إزالة شبكة الأمان الحالية المقدمة في PR #13498 (تبقى كشبكة أمان احتياطية مفيدة).
- تقديم إمكانيات جديدة غير آمنة تتجاوز بوابة
browser.evaluateEnabledالحالية. - إضافة عزل للعمليات (عملية/خيط عامل) للتقييم. إذا ما زلنا نرى حالات تعطل يصعب استردادها بعد هذه الإعادة الهيكلة، فهذه فكرة للمتابعة.
البنية الحالية (لماذا تتعطل)
على مستوى عالٍ:
- يرسل المستدعون
act:evaluateإلى خدمة تحكم المتصفح. - يقوم معالج المسار بالاستدعاء إلى Playwright لتنفيذ JavaScript.
- يقوم Playwright بتسلسل أوامر الصفحة، لذا فإن تقييماً لا ينتهي أبداً يعطل قائمة الانتظار.
- قائمة انتظار عالقة تعني أن عمليات النقر/الكتابة/الانتظار اللاحقة على اللسان قد تبدو متوقفة.
البنية المقترحة
1. نشر الموعد النهائي
تقديم مفهوم ميزانية زمنية واحدة واستخلاص كل شيء منها:
- يحدد المستدعي
timeoutMs(أو موعداً نهائياً في المستقبل). - تستخدم المهلة الزمنية الخارجية للطلب، ومنطق معالج المسار، وميزانية التنفيذ داخل الصفحة جميعها نفس الميزانية، مع هامش صغير حيثما يلزم لتراكب التسلسل.
- يتم نشر الإلغاء كـ
AbortSignalفي كل مكان بحيث يكون الإلغاء متسقاً.
اتجاه التنفيذ:
- إضافة مساعد صغير (على سبيل المثال
createBudget({ timeoutMs, signal })) يعيد:signal: إشارة الإلغاء المرتبطةdeadlineAtMs: الموعد النهائي المطلقremainingMs(): الميزانية المتبقية للعمليات الفرعية
- استخدام هذا المساعد في:
src/browser/client-fetch.ts(HTTP والإرسال داخل العملية)src/node-host/runner.ts(مسار الوكيل)- تنفيذات إجراءات المتصفح (Playwright و CDP)
2. محرك تقييم منفصل (مسار CDP)
إضافة تنفيذ للتقييم يعتمد على CDP ولا يشارك قائمة انتظار الأوامر الخاصة بكل صفحة في Playwright. الخاصية الرئيسية هي أن ناقل التقييم هو اتصال WebSocket منفصل وجلسة CDP منفصلة مرتبطة بالهدف. اتجاه التنفيذ:
- وحدة جديدة، على سبيل المثال
src/browser/cdp-evaluate.ts، تقوم بما يلي:- الاتصال بنقطة نهاية CDP المُهيأة (مقبس على مستوى المتصفح).
- استخدام
Target.attachToTarget({ targetId, flatten: true })للحصول علىsessionId. - تشغيل إما:
Runtime.evaluateللتقييم على مستوى الصفحة، أوDOM.resolveNodeبالإضافة إلىRuntime.callFunctionOnلتقييم العنصر.
- عند انتهاء المهلة أو الإلغاء:
- إرسال
Runtime.terminateExecutionبأفضل جهد للجلسة. - إغلاق اتصال WebSocket وإرجاع خطأ واضح.
- إرسال
ملاحظات:
- هذا لا يزال ينفذ JavaScript في الصفحة، لذا قد يكون للإنهاء آثار جانبية. المكسب هي أنه لا يعطل قائمة انتظار Playwright، ويمكن إلغاؤه على مستوى النقل عن طريق إنهاء جلسة CDP.
3. المرجع (استهداف العناصر دون إعادة كتابة كاملة)
الجزء الصعب هو استهداف العناصر. يحتاج CDP إلى مقبض DOM أو backendDOMNodeId، بينما تستخدم معظم إجراءات المتصفح الحالية محددات Playwright المعتمدة على مراجع من اللقطات. النهج الموصى به: الاحتفاظ بالمراجع الحالية، ولكن إرفاق معرف اختياري قابل للحل عبر CDP.
3.1 توسيع معلومات المرجع المخزنة
توسيع بيانات وصف المرجع المخزنة لدور ما لتشمل اختيارياً معرف CDP:
- اليوم:
{ role, name, nth } - المقترح:
{ role, name, nth, backendDOMNodeId?: number }
هذا يحافظ على عمل جميع إجراءات Playwright الحالية ويسمح لتقييم CDP بقبول نفس قيمة ref عندما يكون backendDOMNodeId متاحاً.
3.2 تعبئة backendDOMNodeId في وقت أخذ اللقطة
عند إنشاء لقطة لدور ما:
- إنشاء خريطة مراجع الدور الحالية كما هو الحال اليوم (الدور، الاسم، الترتيب).
- جلب شجرة AX عبر CDP (
Accessibility.getFullAXTree) وحساب خريطة موازية لـ(role, name, nth) -> backendDOMNodeIdباستخدام نفس قواعد معالجة التكرارات. - دمج المعرف مرة أخرى في معلومات المرجع المخزنة للسان الحالي.
إذا فشل التعيين لمرجع ما، اترك backendDOMNodeId غير محدد. هذا يجعل الميزة بأفضل جهد وآمنة للنشر.
3.3 سلوك التقييم مع المرجع
في act:evaluate:
- إذا كان
refموجوداً وبهbackendDOMNodeId، قم بتشغيل تقييم العنصر عبر CDP. - إذا كان
refموجوداً ولكن لا يحتوي علىbackendDOMNodeId، ارجع إلى مسار Playwright (مع شبكة الأمان).
مخرج اختياري:
- توسيع شكل الطلب لقبول
backendDOMNodeIdمباشرةً للمستدعين المتقدمين (ولأغراض التصحيح)، مع الحفاظ علىrefكواجهة أساسية.
4. الاحتفاظ بمسار استرداد الملاذ الأخير
حتى مع تقييم CDP، هناك طرق أخرى لتعطيل لسان أو اتصال. احتفظ بآليات الاسترداد الحالية (إنهاء التنفيذ + قطع اتصال Playwright) كملاذ أخير لـ:
- المستدعين القدامى
- البيئات التي يتم فيها حظر ربط CDP
- حالات حافة غير متوقعة في Playwright
خطة التنفيذ (تكرار واحد)
المخرجات
- محرك تقييم يعتمد على CDP ويعمل خارج قائمة انتظار الأوامر الخاصة بكل صفحة في Playwright.
- ميزانية زمنية واحدة للمهلة/الإلغاء من البداية إلى النهاية تُستخدم بشكل متسق من قبل المستدعين والمعالجات.
- بيانات وصف المرجع التي يمكنها اختيارياً حمل
backendDOMNodeIdلتقييم العنصر. - تفضل
act:evaluateمحرك CDP عندما يكون ذلك ممكناً وتعود إلى Playwright عندما لا يكون ذلك ممكناً. - اختبارات تثبت أن التقييم العالق لا يعطل الإجراءات اللاحقة.
- سجلات/مقاييس تجعل حالات الفشل والمسارات الاحتياطية مرئية.
قائمة التحقق للتنفيذ
- إضافة مساعد "ميزانية" مشترك لربط
timeoutMs+AbortSignalالمنبع في:AbortSignalواحد- موعد نهائي مطلق
- مساعد
remainingMs()للعمليات اللاحقة
- تحديث جميع مسارات المستدعي لاستخدام ذلك المساعد بحيث يعني
timeoutMsنفس الشيء في كل مكان:src/browser/client-fetch.ts(HTTP والإرسال داخل العملية)src/node-host/runner.ts(مسار وكيل node)- أغلفة CLI التي تستدعي
/act(إضافة--timeout-msإلىbrowser evaluate)
- تنفيذ
src/browser/cdp-evaluate.ts:- الاتصال بمقبس CDP على مستوى المتصفح
Target.attachToTargetللحصول علىsessionId- تشغيل
Runtime.evaluateلتقييم الصفحة - تشغيل
DOM.resolveNode+Runtime.callFunctionOnلتقييم العنصر - عند انتهاء المهلة/الإلغاء:
Runtime.terminateExecutionبأفضل جهد ثم إغلاق المقبس
- توسيع بيانات وصف مرجع الدور المخزنة لتشمل اختيارياً
backendDOMNodeId:- الحفاظ على سلوك
{ role, name, nth }الحالي لإجراءات Playwright - إضافة
backendDOMNodeId?: numberلاستهداف العنصر عبر CDP
- الحفاظ على سلوك
- تعبئة
backendDOMNodeIdأثناء إنشاء اللقطة (بأفضل جهد):- جلب شجرة AX عبر CDP (
Accessibility.getFullAXTree) - حساب
(role, name, nth) -> backendDOMNodeIdودمجها في خريطة المرجع المخزنة - إذا كان التعيين غامضاً أو مفقوداً، اترك المعرف غير محدد
- جلب شجرة AX عبر CDP (
- تحديد توجيه
act:evaluate:- إذا لم يكن هناك
ref: استخدم دائمًا تقييم CDP - إذا حل
refإلىbackendDOMNodeId: استخدم تقييم عنصر CDP - وإلا: ارجع إلى تقييم Playwright (لا يزال محدوداً وقابلاً للإلغاء)
- إذا لم يكن هناك
- الاحتفاظ بمسار الاسترداد "الملاذ الأخير" الحالي كمسار احتياطي، وليس المسار الافتراضي.
- إضافة اختبارات:
- ينتهي التقييم العالق ضمن الميزانية وينجح النقر/الكتابة التالي
- الإلغاء يلغي التقييم (انفصال العميل أو انتهاء المهلة) ويُفك حظر الإجراءات اللاحقة
- حالات فشل التعيين تعود بنظافة إلى Playwright
- إضافة قابلية المراقبة:
- عدادات مدة التقييم وانتهاء المهلة
- استخدام terminateExecution
- معدل الرجوع (CDP -> Playwright) وأسبابه
معايير القبول
- يعيد
act:evaluateالمتعمد تعليقه ضمن ميزانية المستدعي ولا يعطل اللسان للإجراءات اللاحقة. - يتصرف
timeoutMsبشكل متسق عبر CLI، وأداة الوكيل، ووكيل node، والمكالمات داخل العملية. - إذا كان يمكن تعيين
refإلىbackendDOMNodeId، يستخدم تقييم العنصر CDP؛ وإلا فإن المسار الاحتياطي لا يزال محدوداً وقابلاً للاسترداد.
خطة الاختبار
- اختبارات الوحدة:
- منطق مطابقة
(role, name, nth)بين مراجع الأدوار وعقد شجرة AX. - سلوك مساعد الميزانية (الهامش، حساب الوقت المتبقي).
- منطق مطابقة
- اختبارات التكامل:
- ينتهي وقت تقييم CDP ضمن الميزانية ولا يحظر الإجراء التالي.
- الإلغاء يلغي التقييم ويُطلق الإنهاء بأفضل جهد.
- اختبارات العقد:
- التأكد من بقاء
BrowserActRequestوBrowserActResponseمتوافقين.
- التأكد من بقاء
المخاطر والتخفيف منها
- التعيين غير كامل:
- التخفيف: تعيين بأفضل جهد، الرجوع إلى تقييم Playwright، وإضافة أدوات تصحيح.
Runtime.terminateExecutionله آثار جانبية:- التخفيف: الاستخدام فقط عند انتهاء المهلة/الإلغاء وتوثيق السلوك في الأخطاء.
- تراكب إضافي:
- التخفيف: جلب شجرة AX فقط عند طلب اللقطات، التخزين المؤقت لكل هدف، والحفاظ على جلسة CDP قصيرة الأمد.
- قيود وسيط الامتداد:
- التخفيف: استخدام واجهات برمجة التطبيقات للربط على مستوى المتصفح عندما لا تكون المقابس الخاصة بكل صفحة متاحة، والاحتفاظ بمسار Playwright الحالي كاحتياطي.
أسئلة مفتوحة
- هل يجب أن يكون المحرك الجديد قابلاً للتكوين كـ
playwright، أوcdp، أوauto؟ - هل نريد كشف تنسيق "مرجع العقدة" جديد للمستخدمين المتقدمين، أم نكتفي بـ
refفقط؟ - كيف يجب أن تشارك لقطات الإطار واللقطات ذات النطاق المحدد بالمحددات في تعيين AX؟
خطة إعادة هيكلة البث الموحد لوقت التشغيلخطة بوابة OpenResponses