שאלות נפוצות על SmooshGate

מה קרה ל-smoosh?!

ההצעה לתכונה של שפת JavaScript שנקראת Array.prototype.flatten לא תואמת לאינטרנט. שליחת התכונה ב-Firefox Nightly גרמה לשיבושים בלפחות אתר פופולרי אחד. מכיוון שהקוד הבעייתי הוא חלק מספריית MooTools הנרחבת, סביר להניח שיותר אתרים מושפעים מכך. (למרות ש-MooTools לא נמצאים בדרך כלל בשימוש באתרים חדשים בשנת 2018, בעבר הוא היה פופולרי מאוד ועדיין קיים באתרי ייצור רבים.)

מחבר ההצעה הציע את השם של flatten לשם smoosh כבדיחה, כדי למנוע את בעיית התאימות. הבדיחה לא הייתה ברורה לכולם, חלק מהאנשים התחילו להאמין בטעות שהשם החדש כבר הוחלט, והעניין הסלים במהירות.

מה Array.prototype.flatten עושה?

Array.prototype.flat, שהוצע במקור כ-Array.prototype.flatten, משטח מערכים באופן רקורסיבי עד ל-depth שצוין, שברירת המחדל שלו היא 1.

// Flatten one level:
const array = [1, [2, [3]]];
array.flat();
// → [1, 2, [3]]

// Flatten recursively until the array contains no more nested arrays:
array.flat(Infinity);
// → [1, 2, 3]

אותה הצעה כוללת Array.prototype.flatMap, בדומה ל-Array.prototype.map, אבל היא משטחת את התוצאה למערך חדש.

[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]

איך MooTools עושה את הפעולה שגורמת לבעיה הזו?

MooTools מגדיר גרסה לא סטנדרטית משלהם של Array.prototype.flatten:

Array.prototype.flatten = /* non-standard implementation */;

ההטמעה של flatten של MooTools שונה מהתקן המוצע. עם זאת, זו לא הבעיה! כשדפדפנים שולחים Array.prototype.flatten באופן מקומי, MooTools מבטל את ההטמעה המקורית. כך ניתן להבטיח שקוד המסתמך על ההתנהגות של MooTools פועל כמצופה, גם אם האפשרות flatten המקורית זמינה. עד עכשיו, הכל טוב!

לצערנו, משהו אחר קורה. MooTools מעתיק את כל שיטות המערך המותאמות אישית שלו אל Elements.prototype (כאשר Elements הוא ממשק API ספציפי ל-MooTools):

for (var key in Array.prototype) {
  Elements.prototype[key] = Array.prototype[key];
}

for-in מבצע איטרציה על מאפיינים "מספרים", שלא כוללים שיטות מקוריות כמו Array.prototype.sort, אבל כן כוללים מאפיינים שהוקצו באופן קבוע כמו Array.prototype.foo = whatever. אבל – זוהי הכותרת המקדימה – אם מחליפים נכס שלא ניתן לספירה, למשל Array.prototype.sort = whatever, הוא יישאר ללא ספירה.

נכון לעכשיו, Array.prototype.flatten = mooToolsFlattenImplementation יוצר נכס flatten לספירה, ולכן הוא מועתק אל Elements. לעומת זאת, אם דפדפנים שולחים גרסה מקורית של flatten, היא הופכת ללא ספירה ולא מועתקת אל Elements. עכשיו יש קוד לא תקין שמסתמך על השדה Elements.prototype.flatten של MooTools.

למרות שנראה ששינוי הערך של Array.prototype.flatten לברירת המחדל יפתור את הבעיה, סביר להניח שהוא יגרום לבעיות תאימות נוספות. כל אתר שמסתמך על for-in כדי לבצע איטרציה למערך (שיטה לא טובה אבל זה קורה) יקבל פתאום איטרציה נוספת של לולאה לנכס flatten.

הבעיה העמוקה יותר כאן היא שינוי אובייקטים מובנים. הרחבת אבות טיפוס מקוריים מקובלת כיום כשיטה לא תקינה, כי החיבור שלה לא נעים עם ספריות אחרות וקוד של צד שלישי. אל תשנו אובייקטים שלא בבעלותכם!

למה אנחנו לא שומרים על השם הקיים ומבטלים את האינטרנט?

בשנת 1996, לפני ששירות ה-CSS הפך לנרחב, והרבה לפני ש-"HTML5" הפך לשם, האתר של Space Jam הושק. היום האתר עדיין פועל באותו אופן לפני 22 שנה.

איך זה קרה? האם מישהו ניהל את האתר הזה במשך כל השנים האלה ועדכן אותו בכל פעם שספקי דפדפנים שלחו תכונה חדשה?

כפי שהתברר, "dont break the Web" הוא עקרון העיצוב המוביל ל-HTML, ל-CSS, ל-JavaScript ולכל תקן אחר שבו נעשה שימוש נרחב באינטרנט. אם משלוח תכונת דפדפן חדשה גורם לאתרים קיימים להפסיק לפעול, זה מזיק לכולם:

  • מבקרים באתרים המושפעים פתאום נתקלים בחוויית משתמש גרועה;
  • בעלי האתר עברו מאתר שפועל בצורה מושלמת לאתר לא פונקציונלי, בלי שהם שינו משהו;
  • ספקים של דפדפנים ששולחים את התכונה החדשה מאבדים את נתח השוק שלהם בגלל שמשתמשים מחליפים דפדפן אחרי ששמים לב ש"זה עובד בדפדפן X";
  • ברגע שנודע על בעיית התאימות, ספקים אחרים של דפדפנים מסרבים לשלוח אותו. מפרט התכונות לא תואם למציאות ("כל דבר חוץ מיצירה בדיונית"), וזה פוגע בתהליך הסטנדרטיזציה.

נכון, במבט לאחור MooTools עשו דבר לא נכון - אבל פריצה לאינטרנט לא מעניינה אותם, היא מענישה משתמשים. המשתמשים האלה לא יודעים מה זה moo. לחלופין, אנחנו יכולים למצוא פתרון אחר והמשתמשים יכולים להמשיך להשתמש באינטרנט. קל להחליט.

האם המשמעות היא שלעולם לא ניתן להסיר ממשקי API בעייתיים מפלטפורמת האינטרנט?

לשאלה הזו יש כמה תשובות אפשריות. במקרים נדירים, ניתן להסיר מהאינטרנט תכונות בעייתיות. אפילו להבין אם אפשר להסיר תכונה מסוימת הוא מאמץ מורכב, שנדרשים טלמטריה מקיפה כדי לכמת כמה דפי אינטרנט ההתנהגות שלהם תשתנה. אבל אם התכונה לא מאובטחת מספיק, מזיקה למשתמשים או שמשתמשים בה לעיתים רחוקות מאוד, אפשר לעשות זאת.

<applet>, <keygen> ו-showModalDialog() הם דוגמאות לממשקי API לא תקינים שהוסרו בהצלחה מפלטפורמת האינטרנט.

למה אנחנו לא מתקנים את MooTools?

מומלץ לתקן את MooTools כדי להפסיק את הרחבת האובייקטים המובנים. עם זאת, זה לא פותר את הבעיה הנוכחית. גם אם MooTools מוציאים גרסה מתוקנת, כל האתרים הקיימים שמשתמשים בה יצטרכו להתעדכן כדי שבעיית התאימות תיעלם.

האם אנשים לא יכולים פשוט לעדכן את העותק של MooTools?

בעולם מושלם, MooTools מפרסם תיקון, וכל אתר יחיד שמשתמש ב-MooTools מתעדכן באורח פלא ביום המחרת. הבעיה נפתרה, נכון?!

לצערי, זה לא מציאותי. גם אם מישהו יוכל לזהות בצורה כלשהי את כל האתרים המושפעים, למצוא את הפרטים ליצירת קשר עם כל אחד מהם, לפנות בהצלחה לכל בעלי האתר ולשכנע את כולם לבצע את העדכון (כלומר, לארגן מחדש את כל בסיס הקוד שלהם), התהליך כולו עשוי להימשך שנים, לכל הפחות.

חשוב לזכור שרבים מהאתרים האלה ישנים וככל הנראה לא מתוחזקים. גם אם המתחזקת עדיין כאן, יכול להיות שהיא לא מפתחת אתרים עם מומחיות גבוהה כמוכם. אנחנו לא יכולים לצפות מכולם לעבור ולשנות את האתר בן ה-8 שלהם בגלל בעיית תאימות באינטרנט.

איך עובד התהליך של TC39?

TC39 היא הוועדה שאחראית על פיתוח שפת ה-JavaScript באמצעות תקן ECMAScript.

#SmooshGate גרם לאנשים להאמין ש"TC39 רוצה לשנות את השם של flatten ל-smoosh", אבל זו הייתה בדיחה שלא דווחה היטב לגורמים חיצוניים. החלטות חשובות כמו שינוי השם להצעה אינן מתקבלות בקלות, הן לא נלקחות בחשבון בידי אדם יחיד ובהחלט לא נלקחות בן-לילה על סמך תגובה אחת ב-GitHub.

TC39 פועלת לפי תהליך Staging ברור להצעות תכונה. הצעות ECMAScript וכל שינוי משמעותי בהן (כולל שינוי שם השיטה) נדון במהלך ישיבות TC39, וצריך לקבל אישור מלא והוועדה לפני שיהפכו לרשמיות. במקרה של Array.prototype.flatten, ההצעה כבר עברה כמה שלבי הסכם, עד לשלב 3, שמציין שהתכונה מוכנה להטמעה בדפדפני אינטרנט. לעיתים קרובות מופיעות בעיות נוספות במפרט במהלך ההטמעה. במקרה הזה, המשוב החשוב ביותר התקבל אחרי שניסיתם לשלוח אותו: התכונה, במצבה הנוכחי, שוברת את האינטרנט. בעיות קשות לחיזוי כאלה הן חלק מהסיבה לכך שתהליך TC39 לא מסתיים רק ברגע שהדפדפנים שולחים תכונה.

TC39 פועלת לפי הסכמה כללית – כלומר הוועדה חייבת להסכים על כל שינוי חדש. גם אם ההצעה smoosh הייתה חמורה, נראה שחבר ועדה יתנגד לה לטובת שם נפוץ יותר כמו compact או chain.

אף פעם לא נדון בשינוי השם מ-flatten ל-smoosh (גם אם זו לא בדיחה) בפגישה של TC39. לכן, עמדתו הרשמית של TC39 בנושא הזה אינה ידועה כרגע. אף אחד לא יוכל לדבר בשם כל חברי קהילת TC39 עד לקבלת הקונצנזוס בפגישה הבאה.

בפגישות TC39 משתתפים בדרך כלל אנשים מרקעים מגוונים: בחלקם יש שנים של ניסיון בעיצוב בשפת תכנות, אחרים עובדים על דפדפן או על מנוע JavaScript, ויש יותר ויותר משתתפים שמייצגים את קהילת המפתחים של JavaScript.

איך SmooshGate טופל בסופו של דבר?

במהלך ישיבת TC39 במאי 2018, #SmooshGate נפתר באופן רשמי ושינה את השם של flatten לשם flat.

Array.prototype.flat ו-Array.prototype.flatMap נשלחו ב-V8 v6.9 וב-Chrome 69.