مرحباً بالجميع،
لدي بعض المعلومات الجديدة لكم وقد وجدت حلاً لهذه المشكلة.
لذلك، اليوم قمت بالبحث مرة أخرى في هذا الخطأ وأعتقد أنني وجدت المزيد من المعلومات.
من خلال النظر في الملف cmp2ui-fr.js الخاص بـ Quantcast، تمكنت من تحديد مكان حدوث الخطأ، وهو في هذه الدالة (لدينا فقط النسخة المصغرة):
function(t){for(var n in t){t[n].status=e;}}
كما ترون، تستخدم هذه الدالة حلقة for..in، والمتغير t هو مصفوفة. لقد شرحنا ذلك سابقاً، حيث يقوم Ember.js بتوسيع المصفوفة الأصلية في JavaScript. ويبدو أن أحد التعديلات هو إضافة إدخال _super.
يشير إدخال _super إلى دالة ROOT()، والتي تبدو أنها تشير إلى _utils.ROOT في Ember.js (ربما يبدو هذا مألوفاً لبعضكم، لكن ليس لي ^^). هذه الدالة ROOT() غير قابلة للتوسيع.
يبدو أن خاصية _super تعتبر enumerable، مما يعني أنه عند استخدام حلقة for..in على مصفوفة، يُعتبر إدخال _super إدخالاً “عادياً” (على عكس، على سبيل المثال، values، bind، valueOf، أي جميع دوال كائن المصفوفة).
أعتقد أن هذا خطأ في Ember.js وليس سلوكاً مرغوباً فيه.
لذلك، تمكنت من جعل الخطأ قابلاً للتكرار بسهولة. للقيام بذلك، قم بإنشاء مصفوفة من الكائنات، مثل هذا:
var objs = [{'key':'val'},{'key':'val'}];
ثم، قم بإنشاء دالة باستخدام الوضع الصارم، تتكرر فوق مصفوفة وتعيين خاصية جديدة لكل إدخال:
var tst_func = function (objs){'use strict';for(var i in objs){objs[i].newproperty = true }};
أخيراً، قم فقط باستدعاء هذه الدالة على مصفوفة الكائنات:
tst_func(objs);
يجب أن تحصل على خطأ Uncaught TypeError: can't define property "newproperty": Function is not extensible.
النظر في هذا يجعلني أعتقد أن الخطأ موجود بالفعل في الميدان وليس محدداً لـ Quantcast. بشكل أساسي، أي شخص يحاول استخدام for..in يعرض نفسه لسلوك غير متناسق أو خطأ حرج.
بالنسبة لي، الأمر لا يتعلق بـ Discourse أو Quantcast، بل بوضوح بـ Ember.js. ومع ذلك، لا يغير ذلك حقيقة أننا بحاجة إلى إيجاد حل لها طالما لم يتم إصلاحها في Ember.js ^^.
الخبر السار هو أنني أعتقد أنني وجدت طريقة لإصلاح هذا.
إحدى الطرق للقيام بذلك هي استخدام سطر if (!objs.hasOwnProperty(i)) {continue}; في كل حلقة for..in (وربما أيضاً each، for of، إلخ). هذا لا يغير السلوك الغريب للمصفوفة _super، لكنه يمنع الوصول إليه محلياً. وهذا يعني بالطبع أن هذا لا يعمل مع أي سكريبت خارجي لا نسيطر عليه، مثل حالة استخدام Quantcast الخاصة بي.
طريقة أخرى، والتي أعتقد أنها المسار الصحيح، هي تعديل نموذج المصفوفة في JavaScript (لذلك نحن في الأساس نلغي تجاوز Ember.js الخاص به ^^) لجعل _super غير قابل للعد. للقيام بذلك، يجب علينا تشغيل سطر JS هذا بعد استدعاء Ember.js وتقييمه:
//Make _super not enumerable to prevent bug between emberjs and for..in
Object.defineProperty(Array.prototype, '_super', {'enumerable': false});
الطريقة الثانية تسمح بالاستخدام المباشر لـ _super، كما كان من المفترض، وتمنع ظهوره في الحلقات. ومع ذلك، لا يمكنني ضمان عدم استخدام هذا السلوك الغريب من قبل أي دالة داخلية في Ember.js أو إضافة خارجية.
بالنظر إلى الملف _ember_jquery-189e46ebcb33594b835e782fd1ce916ec750bc0cf980ebc4fb7796649161a18d.js، رأيت بعض الأسطر المحددة لـ Discourse، مثل:
var ALIASES = {
"ember-addons/ember-computed-decorators":
"discourse-common/utils/decorators",
"discourse/lib/raw-templates": "discourse-common/lib/raw-templates",
"preload-store": "discourse/lib/preload-store",
"fixtures/user_fixtures": "discourse/tests/fixtures/user-fixtures",
};
var ALIAS_PREPEND = {
fixtures: "discourse/tests/",
helpers: "discourse/tests/",
};
ربما يمكننا إضافة سطر Object.defineProperty(Array.prototype, '_super', {'enumerable': false}); هنا؟
بالنسبة لي، قمت حالياً بإصلاح الخطأ بإضافة الأسطر:
//Make _super not enumerable to prevent bug between emberjs and for..in
Object.defineProperty(Array.prototype, ‘_super’, {‘enumerable’: false});
قبل استدعاء سكريبت Quantcast choice.js.
أعتقد أن شخصاً ما يمكنه إصلاح الخطأ محلياً بإنشاء ملف ‘fix_ember.js’ يحتوي على هذين السطرين، وخدمته بشكل ثابت من خلال الوكيل العكسي (على سبيل المثال Nginx)، وإضافة سطر <script src="/fix_emmber.js"></script> في تذييل الموضوع باستخدام التخصيص. لا يعمل كتابة السكريبت مباشرة بدلاً من إنشاء رابط بسبب استخراج السكريبت في Discourse (انظر Custom javascript in <head> disappear).
آمل أن يساعد هذا الموضوع الآخرين. سأفتح تذكرة في Ember.js غداً، لمعرفة ما إذا كان هذا خطأ أو سلوكاً غريباً جداً ولكنه متعمد.
سأبقيكم على اطلاع لمعرفة ما إذا كان علينا تضمين إصلاح في Discourse.
ملاحظة: شكراً جزيلاً لـ Angus Croll من https://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/، ساعدني منشوره كثيراً!