توقف/انتهت مقاطع فيديو YouTube من التشغيل تلقائيًا عند التمرير لأسفل بما يكفي لتحميل منشورات جديدة

هل هناك خطأ أو صعوبة في تصحيح virtual-dom لحل هذه المشكلة؟

نرحب بطلب سحب (PR)، لقد حاولنا ولكن كان الأمر صعبًا للغاية ببساطة

إعجابَين (2)

مثير للاهتمام للغاية! الانتقال إلى تفرع من vdom ليس مثاليًا، ولكن قد نتمكن من النظر فيه طالما يمكننا إثبات عدم وجود أي تراجعات (وأننا ننقله إلى مؤسسة GitHub الخاصة بنا).

هل تمكنت من تشغيل مجموعة اختبارات vdom للتأكد من عدم وجود أي تراجعات؟ ما مدى سهولة إضافة اختبار vdom جديد لسلوك الإلحاق هذا؟

إعجابَين (2)

سأتناول السؤال الثاني أولاً. هذا السلوك الإضافي هو نفسه في الأساس، فهو يزيل فقط بعض العمل الإضافي. سأحاول توضيح ما يفعله vdom في الأصل وبعد التصحيح.

لنفترض أن هناك 20 منشورًا ويتم تحميل 10 منها في الأعلى بعد التمرير.
في الأصل يقوم vdom بتنفيذ هذه السلسلة من التحويلات:
[20 قديم] → [20 قديم، 10 جديد] // يتم إلحاق 10 عناصر جديدة في النهاية
[20 قديم، 10 جديد] → // تتم إزالة جميع العناصر الـ 30
→ [10 جديد، 20 قديم] // يتم إدراج جميع العناصر الـ 30 في مكانها
بعد التصحيح تصبح السلسلة:
[20 قديم] → [20 قديم، 10 جديد] // يتم إلحاق 10 عناصر جديدة في النهاية
[20 قديم، 10 جديد] → [20 قديم] // تتم إزالة 10 عناصر جديدة من النهاية
[20 قديم] → [10 جديد، 20 قديم] // يتم إضافة 10 عناصر جديدة في البداية
كما ترى، لا يزال هناك عمل إضافي: من حيث المبدأ، يمكنك إضافة هذه العناصر في البداية على الفور، ولكن بهذه الطريقة يمكنني فقط إضافة بعض التعليمات البرمجية في مكان واحد وعدم القلق بشأن إعادة كتابة ما هو موجود بالفعل.
تصبح كل عملية تحويل عملية DOM، لذلك تبدأ مقاطع فيديو YouTube في التشغيل لأن العناصر القديمة يتم إعادة إدراجها في الأصل (مما يؤدي إلى إعادة عرضها)، وبعد التصحيح تظل في مكانها.

إعجابَين (2)

هنا مقتطف من ملف package.json الخاص بـ virtual-dom

"scripts": {
    "test": "node ./test/index.js | tap-spec",
    "dot": "node ./test/index.js | tap-dot",
    "start": "node ./index.js",
    "cover": "istanbul cover --report html --print detail ./test/index.js",
    "view-cover": "istanbul report html & opn ./coverage/index.html",
    "browser": "run-browser test/index.js",
    "phantom": "run-browser test/index.js -b | tap-spec",
    "dist": "browserify --standalone virtual-dom index.js > dist/virtual-dom.js",
    "travis-test": "npm run phantom && npm run cover && istanbul report lcov && ((cat coverage/lcov.info | coveralls) || exit 0)",
    "release": "npm run release-patch",
    "release-patch": "git checkout master && npm version patch && git push origin master --tags && npm publish",
    "release-minor": "git checkout master && npm version minor && git push origin master --tags && npm publish",
    "release-major": "git checkout master && npm version major && git push origin master --tags && npm publish"
  },

من بين هذه، تبدو ‘test’، ‘dot’، ‘cover’، ‘view-cover’، ‘browser’، ‘phantom’، ‘travis-test’ ذات صلة بالاختبار.
تعطي ‘browser’، ‘phantom’، ‘travis-test’ خطأ في التحليل بسبب تراكيب جافاسكريبت أحدث في الكود الخاص بي. تمر الأخرى. إذا قمت بتغيير هذا الكود

        var prepend = simulate.every(item => item && item.key)
        prepend &= aChildren.every((item, i) => item.key === bChildren[i + shift].key)

إلى هذا الكود

        var prepend = true
        for (var i = 0; prepend && i < simulate.length; i++) {
            prepend = simulate[i] && simulate[i].key
        }
        for (var i = 0; prepend && i < aChildren.length; i++) {
            prepend = aChildren[i].key === bChildren[i + shift].key
        }

فإن الكل يمر. يمكنني دفع هذا التغيير للحفاظ على جافاسكريبت قديمًا بشكل متسق إذا كان إرضاء جميع هذه النصوص مرغوبًا فيه.

إعجابَين (2)

:+1: من فضلك افعل - دعنا نحافظ على مجموعة الاختبار الحالية الخاصة بهم تعمل

لقد قمت للتو بعمل نسخة من virtual-dom إلى GitHub - discourse/virtual-dom: A Virtual DOM and diffing algorithm - هل يمكنك تقديم طلب سحب ضد هذا المستودع؟

3 إعجابات
3 إعجابات

يجب أن أشير أيضًا إلى أن تغييري في virtual-dom ضيق جدًا. إنه يستهدف الإضافات (prepends) على وجه التحديد ويتراجع إلى الخوارزمية الأصلية في جميع الحالات الأخرى. وهذه الخوارزمية الأصلية لا تزال غير مثالية إذا نظرت إلى المشكلة بشكل عام (ليس من الصعب ابتكار أمثلة، عندما تلمس عناصر قديمة بشكل غير ضروري). من ناحية أخرى، فهي تتعامل مع الإضافات (appends) والإزالات والإدراجات الفردية بشكل جيد. ومع هذا، تحتاج إلى أن تكون متطورًا جدًا مع التدفق اللاحق (post stream) للانفصال. لذا، من الناحية العملية، قد يكون حل المشكلة بشكل عام مبالغًا فيه بعض الشيء، على الرغم من أنه يمكنك بالطبع النوم بشكل أفضل عندما تفعل ذلك.

لقد قمت بدفع بعض الاختبارات الجديدة. هل تخطط لمراجعة طلب السحب في أي وقت قريب؟

إعجاب واحد (1)

شكراً إليكسي - سأحاول مراجعتها خلال الأسبوع القادم

4 إعجابات

لقد قمت بإعداد نسخة من virtualdom، ويمكنني تأكيد أنها تحل مشكلة iframe في الاختبار اليدوي.

@Aleksey_Bogdanov أتساءل عما إذا كان بإمكانك مساعدتي في شيء ما. لقد كنت أحاول إضافة اختبار داخل Discourse. بشكل أساسي:

  1. قم بعرض <span>ElementOne</span><span>ElementTwo</span>

  2. قم بإزالة ElementTwo، وقم بإلحاق PrependedElement

  3. تحقق من أن النتيجة هي <span>PrependedElement</span><span>ElementOne</span>

  4. تحقق من أن عنصر span الأصلي ElementOne يساوي عنصر span النهائي ElementOne (أي تحقق من أنه لم يتم إعادة عرضه)

للأسف، فشل التحقق في (4)، مما يعني أنه تم إعادة عرض ElementOne. أي فكرة لماذا لا يعمل المنطق الجديد في هذه الحالة؟ :thinking:

لقد قمت بدفع تكوين النسخة الجديدة والاختبار الفاشل إلى PR الحالي.

3 إعجابات

نعم، لقد كتبت عن هذا سابقًا.
لا أتوقع أن يعمل هذا بشكل عام (وأن ينجح الاختبار كما وصفته). في الأصل، كان يعمل مع الإضافات، والإزالات، والإدخالات الفردية (وربما مزيج منها). مع تغييري، فإنه يعمل أيضًا مع الإضافات البحتة، والتي يجب أن تغطي خطأ يوتيوب. يتضمن اختبارك “إزالة + إضافة”. هذا غير مغطى بتغييري.
الحل الأكثر قوة سيتطلب إعادة كتابة كبيرة لـ “reorder” و “diffChildren” في virtual-dom على الأقل. يمكنني محاولة ذلك، ولكنه يطرح السؤال، هل تخطط للاحتفاظ بنسختك الخاصة من virtual-dom على المدى الطويل؟ إذا كنا نحاول أن نكون أقوياء، فقد تكون فكرة أفضل وتتطلب وقتًا وجهدًا أقل لمحاولة التبديل إلى مكتبة مماثلة يتم صيانتها بنشاط. تخميني هو أن المكتبات الأخرى قد حلت هذه المشكلة بالفعل بحلول الآن.

إعجابَين (2)

أرى - هذا منطقي. ومع ذلك، حتى لو جعلته ‘إلحاقًا خالصًا’، أحصل على نفس الفشل. إسقاط نقطة توقف في دالة reorder() ذات الصلة يظهر أنها تتعطل عند التحقق bFree.length === bChildren.length:

لقد دفعت الاختبار المحدث إلى الفرع.

هذا بالتأكيد حل قصير الأجل فقط. لقد بدأنا بالفعل في استبدال استخدامنا لـ vdom بعرض Ember/Glimmer. هدفنا هو استبدال تنفيذ تدفق ما بعد النشر خلال الـ 12 شهرًا القادمة. Glimmer يتعامل مع هذا النوع من ‘الإلحاق’ بشكل صحيح.

لذلك، يسعدني تمامًا دمج تغيير ‘غير مكتمل، ولكنه أفضل من ذي قبل’. ولكن، إذا لم يكن الأمر يتطلب الكثير من العمل، فسيكون من الجيد فهم سبب عدم عمل هذا الاختبار :thinking:

3 إعجابات

بالتأكيد. لست متأكدًا بعد، ولكني سأبحث في الأمر في أقرب وقت ممكن.

3 إعجابات

تحديث.
لقد أضفت مفاتيح لاجتياز الاختبار. تشير المفاتيح إلى virtual-dom أي العناصر تتوافق مع أي منها. بدونها، يفترض virtual-dom ببساطة أن العناصر تتبع نفس الترتيب السابق ولا يمكنه معرفة أنه يتعامل مع عمليات الإلحاق.
ثم قمت بتغيير الإلحاق الفردي إلى عمليات إلحاق متعددة لأن virtual-dom غطى بالفعل عمليات الإدراج الفردية (وعمليات الإلحاق الفردية هي حالة خاصة)، لذلك لا ينبغي أن تحدث فرقًا.
التغييرات المذكورة أعلاه هي ما دفعته حتى الآن.

ولكن الآن عمليات الإلحاق المتعددة لا تحدث فرقًا، وهو أمر مفاجئ. قد تكون نظريتي الأولية حول الخطأ، وبالتالي سبب نجاح التصحيح الخاص بي، معيبة. لذلك ما زلت أحاول معرفة ذلك.
ألاحظ، يا ديفيد، أنك قمت بتصحيح الاختبار في المتصفح. هل من الصعب إعداده؟ أواجه صعوبة في إعداد مصحح الأخطاء للاختبارات وسأكون ممتنًا لو أمكنك إعطائي بعض التوجيهات.

3 إعجابات

آها، فهمت - شكرًا لك!

هل لديك إعداد تطوير Discourse يعمل؟ إذا كان الأمر كذلك، فقم بتشغيله، وقم بزيارة /tests في المتصفح، ثم استخدم واجهة التصفية في الأعلى للبحث عن “avoids rerendering on prepend”. بعد ذلك، يمكنك استخدام أدوات مطوري المتصفح لتصحيح الأخطاء. (على سبيل المثال، انتقل إلى علامة التبويب المصادر، واضغط على Ctrl+P لفتح الملف، وابحث عن vdom/diff، وقم بتعيين نقطة توقف)

3 إعجابات

شكراً لك، سأجرب ذلك.

3 إعجابات

إذًا، هذا الكود

assert.strictEqual(elementOneBefore, elementOneAfter);

لا يُحدث فرقًا لأن elementOneBefore يحافظ على هويته عبر كل هذه التغييرات بغض النظر عن ذلك.
إليك توضيح بسيط، إذا كنت ترغب في رؤية ذلك بنفسك:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Youtube Bug Demo</title>
</head>
<body>
    <script>
        let iframe = document.createElement("iframe");
        iframe.width = 690;
        iframe.height = 388;
        iframe.src = "https://www.youtube.com/embed/Xc5rB-0ZBcI";
        iframe.title = "Strange S.T.A.L.K.E.R. car glitch";
        document.body.appendChild(iframe);
        
        let button = document.createElement("button");
        button.type = "button";
        button.innerHTML = "Reinsert";
        button.onclick = function(){
            let iframeStart = document.querySelector("iframe");
            document.body.removeChild(iframeStart);
            document.body.insertBefore(iframeStart, button);
            let iframeEnd = document.querySelector("iframe");
            alert(iframeStart === iframeEnd);
        };
        document.body.appendChild(button);
    </script>
</body>
</html>

ما يُحدث فرقًا هو استدعاءات ‘removeChild’ و ‘insertBefore’، لذلك أضفت فحصًا لطفرات DOM. الآن يفشل الاختبار للإصدار السابق ويمر للإصدار الحالي، لذا نأمل أن يكون هذا كافيًا.

6 إعجابات

هذا رائع، شكراً جزيلاً على عملك هنا @Aleksey_Bogdanov. لقد قمت بدمج طلب السحب - سيكون متاحًا على Meta في غضون الساعة القادمة.

6 إعجابات