Xterm.js: تعطل المتصفح المرتبط بملاءمة الملحق العائد للهندسة بأحجام "إنفينيتي"

تم إنشاؤها على ٢٦ أبريل ٢٠١٨  ·  26تعليقات  ·  مصدر: xtermjs/xterm.js

screenshot 2018-04-25 18 34 47

يبدو أنه ناتج عن حالات الحافة حول xterms خارج الشاشة التي تظهر / تظهر على الشاشة. باستخدام term.renderer.dimensions.actualCellWidth كـ null ، يتم إرجاع القيمة المناسبة Infinity . إذا سمحت لـ xterm بمحاولة تغيير حجم نفسه إلى Infinity ، فإنه يستهلك كل ذاكرة الوصول العشوائي المتاحة ويعطل المتصفح.

areaddofit help wanted typbug

التعليق الأكثر فائدة

لقد لاحظت للتو أن xterm يشترط أن يكون الوالد مرئيًا عند استدعاء open . قد نكون مخطئين ، لذا سأحاول إلقاء نظرة ثانية لاحقًا.

ال 26 كومينتر

إليك برنامج CodePen الذي يتم إعادة إنتاجه في الغالب: https://codepen.io/akanet/pen/zjBgXa

Tyriar آسف للتذمر ، هل لديك فرصة لإلقاء نظرة على هذا واحد؟

أعتقد أنني أواجه نفس المشكلة.

أضفت ما يلي في نهاية تلك الوظيفة

    console.log("fit proposed geometry", geometry);
    if (geometry.cols == Infinity || geometry.rows == Infinity) {
      return null;
    }

لكن الملاءمة الآن لا تعمل على الإطلاق. أعتقد أنه مكسور.

لقد حشيت هذا في الأعلى:

var cellWidth = term.renderer.dimensions.actualCellWidth || 10;
var cellHeight = term.renderer.dimensions.actualCellHeight || 15;

والتعديل المناسب للأسفل:

    var geometry = {
        cols: Math.floor(availableWidth / cellWidth),
        rows: Math.floor(availableHeight / cellHeight)
    };

بدأت الأمور في العمل بشكل أفضل قليلاً ، لكن من الواضح أن الملاءمة غير صحيحة.

إذا وضعت هذا في الجزء العلوي من الملاءمة:

    if (!cellWidth || !cellHeight)
      return null;

وليس لديها إعدادات افتراضية ، فهي لا تعرض بشكل صحيح أبدًا ، وبالتالي فإن حقول العارض actualCell* لا تحصل أبدًا على قيمة.

أقوم بالتخفيف حاليًا عن طريق التخلف عن بعض القيم العاقلة (ولكن الخاطئة) في حالة Infinity ، وإعادة تشغيل fit عند انتهاء المهلة. إنها ليست مثالية.

نعم ، لكني لا أفهم لماذا من الضروري التقصير في القيمة الخاطئة .... أنا فقط أحاول معرفة ذلك.

بطريقة ما ، إذا اتصلت بـ terminal.resize(NaN, NaN) ، فسيبدأ العمل في النهاية. ولكن إذا اتصلت بأي شيء آخر ، على سبيل المثال terminal.resize(10, 10) ، فلن يعمل أبدًا.

        //this.terminal.fit();
        this.terminal.resize(NaN, NaN);

فقط يبدو خاطئ جدا.

حرفيا لا يعمل على الإطلاق إذا لم يكن لدي ذلك. يتم استدعاء الوقت المناسب الوحيد عندما يتغير حجم العنصر الأصلي.

بطريقة ما ، لا يحسب العارض القيم إلا إذا فعلت ذلك.

هذا ما انتهيت إليه ، هذا يعمل. جاه.

Terminal.prototype.proposeGeometry = function() {
        if (!this.element.parentElement) {
                return null;
        }

        var cellWidth = this.renderer.dimensions.actualCellWidth || 9;
        var cellHeight = this.renderer.dimensions.actualCellHeight || 17;
        var parentElementStyle = window.getComputedStyle(this.element.parentElement);
        var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
        var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));
        var elementStyle = window.getComputedStyle(this.element);
        var elementPadding = {
                top: parseInt(elementStyle.getPropertyValue('padding-top')),
                bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')),
                right: parseInt(elementStyle.getPropertyValue('padding-right')),
                left: parseInt(elementStyle.getPropertyValue('padding-left'))
        };
        var elementPaddingVer = elementPadding.top + elementPadding.bottom;
        var elementPaddingHor = elementPadding.right + elementPadding.left;
        var availableHeight = parentElementHeight - elementPaddingVer;
        var availableWidth = parentElementWidth - elementPaddingHor - this.viewport.scrollBarWidth;
        var geometry = {
                cols: Math.floor(availableWidth / cellWidth),
                rows: Math.floor(availableHeight / cellHeight)
        };
                // This is still sometimes NaN, NaN !?
        return geometry;
}

Terminal.prototype.fit = function() {
    var geometry = this.proposeGeometry();

    if (geometry) {
        if (this.rows !== geometry.rows || this.cols !== geometry.cols) {
            this.renderer.clear();
            this.resize(geometry.cols, geometry.rows);
        }
    }
}

لقد لاحظت للتو أن xterm يشترط أن يكون الوالد مرئيًا عند استدعاء open . قد نكون مخطئين ، لذا سأحاول إلقاء نظرة ثانية لاحقًا.

أرى. لست متأكدًا حتى من كيفية ضمان ذلك باستخدام etch و atom . لا أعرف ما إذا كان هناك نوع من الخطاف ، مثل onParentVisible ؟

لقد توصلت إلى حل بناءً على ما قلته.

لقد نقلت terminal.open إلى معالج تغيير الحجم. انها عملت. لذلك ، يتم إنشاء المكون على dom ظاهري ، ثم بمجرد إضافته إلى الأصل الحقيقي ، يتم استدعاء تغيير الحجم ، ويقوم بإعداد المحطة الفعلية.

لقد لاحظت للتو شرط أن xterm يجب أن يكون الوالد مرئيًا عند استدعاء الفتح. قد نكون مخطئين ، لذا سأحاول إلقاء نظرة ثانية لاحقًا.

نعم ، يجب أن تكون قادرًا على حلها عن طريق التحقق مما إذا كان العنصر مرفقًا قبل الاتصال بـ fit :

if (term.element) {
  term.fit();
}

لذلك ، يتم إنشاء المكون على دوم افتراضي

في هذه الحالة ، ستحتاج إلى طريقة أخرى للتعامل مع هذا الأمر ، ربما عن طريق تتبع ما إذا كان مرتبطًا حقًا (لماذا يتم إرفاقه بـ dom افتراضي؟)


لإغلاق هذه المشكلة ، ربما يتعين علينا إضافة تحقق فارغ على بعض خصائص الأبعاد داخل fit حتى لا يحاول الحجم إلى Infinity ؟

حتى إذا كان term.element موجودًا ، فقد لا يكون العنصر الأصل موجودًا ، لذلك لا يزال يفشل.

لماذا يتم إلحاقه بـ Dom الظاهري؟

لأنه يتم استخدامه داخل Etch / atom.

https://atom.io/packages/script-runner

لا أعرف ما إذا كانت هناك طريقة أفضل للقيام بذلك.

Tyriar تمامًا مثل ، xterm تنشر lib رائعًا ، ولدى lib خطأ خطير يتسبب في تعطل المتصفح الخاص بي ، ومجموعة xterm تخبر المطور فقط الانتباه إلى هذا.
بالطبع ، يمكنني إضافة فحص. لكن أعتقد أن معظم المطورين لن يهتموا بهذا الخطأ ، بما في ذلك مجموعة xterm. ويمكننا إصلاح هذا الخطأ بسهولة عن طريق إضافة بعض التعليمات البرمجية الوقائية لمنعه (على سبيل المثال: تعيين الحد الأقصى للصفوف الافتراضية والحد الأقصى للعمود). لماذا لا نفعلها

يجب عليك بالتأكيد التحقق من أنه سيخصص فقط عددًا محدودًا من الصفوف والأعمدة ... لا يلزم أن يكون حدًا أقصى ... فقط تحقق من صحة الحجج ليست إنفينيتي.

ioquatix نعم ، قد لا نحتاج إلى الحد الأقصى ، أضف أقصى عدد من الصفوف مجرد حل لاقتراحي. أعني أن xterm يجب أن تضيف كود الحماية. لا تطلب فقط من آلاف المطورين إضافة رمز التحقق.
السبب الجذري لهذا الخطأ هو أن هذه الأسطر لا تحتوي على كود حماية.
https://github.com/xtermjs/xterm.js/blob/master/src/Terminal.ts#L1941
https://github.com/xtermjs/xterm.js/blob/master/src/Buffer.ts#L150

أعتقد أنه من المعقول إجراء فحوصات استباقية. لا ينبغي أن يكون من الممكن أن تكون الأعداد الصحيحة NaN ، لكن ها نحن ذا ، إنها JavaScript. لذلك ، من المنطقي التأكد من أن الأرقام ليست ، على سبيل المثال ، سلبية ، NaN ، Infinity ، إلخ.

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

@ kevinwon1985 قلت

لإغلاق هذه المشكلة ، ربما يجب أن نضيف فحصًا فارغًا على بعض خصائص الأبعاد داخل الملاءمة حتى لا تحاول الحجم إلى Infinity؟

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

Tyriar لا توجد قيمة قصوى على ما يرام. أعتقد أن مجرد إضافة بعض الشيك داخل fit لا يكفي. قد يرتكب المطورون الآخرون نفس الخطأ عند استدعاء resize ، تمامًا مثل الوظيفة الإضافية المناسبة. هل يجب أن نضيف بعض الشيكات داخل resize ؟

1 / أعتقد أنه إذا كان الحجم غير صالح ، فيجب أن يكون خطأ.

2 / إذا كان الحجم كبيرًا جدًا بالنسبة لذاكرة الكمبيوتر المتاحة ، فيجب أن يكون خطأ أيضًا ، وليس تعطل المتصفح.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

albinekb picture albinekb  ·  4تعليقات

LB-J picture LB-J  ·  3تعليقات

travisobregon picture travisobregon  ·  3تعليقات

tandatle picture tandatle  ·  3تعليقات

chris-tse picture chris-tse  ·  4تعليقات