Najczęstsze pytania dotyczące SmooshGate

Co się stało z smoosh?

Proponowana funkcja języka JavaScript o nazwie Array.prototype.flatten okazuje się niezgodna z internetem. Wprowadzenie tej funkcji w Firefox Nightly spowodowało usterkę co najmniej jednej popularnej witryny. Ponieważ problematyczny kod jest częścią popularnej biblioteki MooTools, prawdopodobnie dotyczy to znacznie większej liczby witryn. (chociaż w 2018 r. MooTools nie jest często używany do tworzenia nowych witryn, był bardzo popularny i nadal jest obecny w wielu witrynach produkcyjnych).

Autor propozycji zażartował, że aby uniknąć problemów ze zgodnością, można zmienić nazwę flatten na smoosh. Żart nie był jasny dla wszystkich, więc niektórzy użytkownicy zaczęli błędnie sądzić, że nowa nazwa została już wybrana, i sytuacja szybko się nasiliła.

Co robi Array.prototype.flatten?

Funkcja Array.prototype.flat, pierwotnie zaproponowana jako Array.prototype.flatten, spłaszcza tablice rekurencyjnie aż do określonej wartości depth, która domyślnie wynosi 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]

Ta sama propozycja zawiera funkcję Array.prototype.flatMap, która jest podobna do funkcji Array.prototype.map, ale spłaszcza wynik w nowej tablicy.

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

Co powoduje ten problem?

MooTools definiuje własną niestandardową wersję Array.prototype.flatten:

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

Implementacja flatten w MooTools różni się od proponowanego standardu. To jednak nie jest problem. Gdy przeglądarki udostępniają Array.prototype.flatten natywnie, MooTools zastępuje natywną implementację. Dzięki temu kod korzystający z zachowania MooTools działa zgodnie z oczekiwaniami niezależnie od tego, czy natywna funkcja flatten jest dostępny. Póki co idzie dobrze.

Niestety, potem dzieje się coś innego. MooTools kopiuje wszystkie niestandardowe metody tablic do Elements.prototype (gdzie Elements jest interfejsem API specyficznym dla MooTools):

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

for-in iteruje właściwościami „enumerowanymi”, które nie obejmują metod natywnych, takich jak Array.prototype.sort, ale obejmują właściwości przypisane regularnie, takie jak Array.prototype.foo = whatever. Ale – i tutaj jest haczyk – jeśli zastąpisz właściwość niewyliczalną, np. Array.prototype.sort = whatever, pozostanie ona niewyliczalną.

Obecnie funkcja Array.prototype.flatten = mooToolsFlattenImplementation tworzy wyliczalną właściwość flatten, która jest później kopiowana do Elements. Jeśli jednak przeglądarki udostępniają natywną wersję elementu flatten, staje się on niewyliczalny i nie jest kopiowany do elementu Elements. Każdy kod korzystający z biblioteki MooToolsElements.prototype.flatten jest teraz uszkodzony.

Chociaż wydaje się, że zmiana domyślnego elementu Array.prototype.flatten na enumerable rozwiąże problem, prawdopodobnie spowoduje jeszcze więcej problemów ze zgodnością. Każda witryna, która używa instrukcji for-in do iteracji w tablicy (co jest złą praktyką, ale zdarza się), nagle uzyskałaby dodatkową iterację pętli dla właściwości flatten.

Głównym problemem jest tutaj modyfikowanie wbudowanych obiektów. Rozszerzanie prototypów natywnych jest obecnie powszechnie uznawane za złą praktykę, ponieważ nie komponuje się dobrze z innymi bibliotekami i kodem innych firm. Nie modyfikuj obiektów, które do Ciebie nie należą.

Dlaczego nie pozostawimy dotychczasowej nazwy i nie zerwiemy internetu?

W 1996 r., zanim stała się powszechna technologia CSS, a zanim „HTML5” stało się czymś ważnym, opublikowano witrynę Space Jam. Obecnie strona działa tak samo jak 22 lata temu.

Jak to się stało? Czy przez te wszystkie lata ktoś zajmował się tą witryną, aktualizując ją za każdym razem, gdy dostawcy przeglądarek wprowadzali nową funkcję?

Okazuje się, że „nie psuj internetu” to główna zasada projektowania kodu HTML, CSS, JavaScriptu i innych standardów powszechnie używanych w internecie. Jeśli wdrożenie nowej funkcji przeglądarki powoduje, że istniejące witryny przestają działać, jest to niekorzystne dla wszystkich:

  • użytkownicy dotkniętych witryn nagle odczuwają pogorszenie jakości usług;
  • właściciele witryny przeszli od witryny, która działała idealnie, do niedziałającej, bez wprowadzania jakichkolwiek zmian;
  • dostawcy przeglądarek udostępniający nową funkcję tracą udział w rynku, ponieważ użytkownicy przełączają się na przeglądarki, które „działają w przeglądarce X”;
  • Gdy problem ze zgodnością stanie się znany, inni dostawcy przeglądarek odmówią jego udostępnienia. Specyfikacja funkcji nie odpowiada rzeczywistości („to tylko fikcja”), co nie sprzyja procesowi standaryzacji.

Z pewnością MooTools popełniło błąd, ale zepsucie internetu nie jest karą dla MooTools, tylko dla użytkowników. Ci użytkownicy nie wiedzą, czym jest narzędzie moo. Możemy też znaleźć inne rozwiązanie, dzięki któremu użytkownicy będą mogli nadal korzystać z Internetu. Wybór jest prosty.

Czy to oznacza, że złe interfejsy API nigdy nie mogą zostać usunięte z platformy internetowej?

To zależy. W rzadkich przypadkach niektóre funkcje mogą zostać usunięte z Internetu. Nawet ustalenie, czy możliwe jest usunięcie danej funkcji, jest bardzo trudne i wymaga rozbudowanej telemetrii, aby określić, ile stron internetowych zmieniłoby swoje działanie. Może się to jednak zdarzyć, gdy funkcja jest niewystarczająco bezpieczna, szkodliwa dla użytkowników lub używana bardzo rzadko.

<applet>, <keygen> i showModalDialog() to przykłady nieprawidłowych interfejsów API, które zostały usunięte z platformy Web Platform.

Dlaczego nie naprawimy MooTools?

Dobrym pomysłem jest wstawienie poprawki do MooTools, aby nie rozszerzała już wbudowanych obiektów. Nie rozwiązuje jednak problemu. Nawet gdyby MooTools opublikowało zaktualizowaną wersję, wszystkie istniejące witryny, które z niej korzystają, musiałyby zostać zaktualizowane, aby problem ze zgodnością zniknął.

Czy użytkownicy nie mogą po prostu zaktualizować swojej kopii MooTools?

W idealnym świecie MooTools udostępniałaby poprawkę, a następnego dnia każda witryna korzystająca z MooTools zostałaby magicznie zaktualizowana. Problem rozwiązany, prawda?

Niestety, jest to nierealne. Nawet jeśli udałoby się zidentyfikować wszystkie witryny, które są dotknięte problemem, znaleźć informacje kontaktowe do każdej z nich, skontaktować się z właścicielami i przekonać ich do wprowadzenia aktualizacji (co może wymagać przeprojektowania całej bazy kodu), cały proces w najlepszym razie zajęłby lata.

Pamiętaj, że wiele z tych witryn jest starych i prawdopodobnie nie jest już aktualizowanych. Nawet jeśli administrator nadal pracuje nad projektem, może nie być tak doświadczonym programistą stron internetowych jak Ty. Nie możemy oczekiwać, że wszyscy użytkownicy zmienią swoją 8-letnią stronę internetową z powodu problemu ze zgodnością.

Jak wygląda proces TC39?

TC39 to komitet odpowiedzialny za ulepszanie języka JavaScript za pomocą standardu ECMAScript.

#SmooshGate spowodował, że niektórzy użytkownicy uwierzyli, że „TC39 chce zmienić nazwę flatten na smoosh”, ale był to żart, który nie został dobrze zakomunikowany na zewnątrz. Ważne decyzje, takie jak zmiana nazwy propozycji, nie są podejmowane lekkomyślnie, nie są podejmowane przez jedną osobę i zdecydowanie nie są podejmowane z dnia na dzień na podstawie jednego komentarza na GitHubie.

TC39 stosuje jasny proces wdrażania propozycji funkcji. Propozycje ECMAScript i wszelkie istotne zmiany w nich (w tym zmiana nazwy metody) są omawiane podczas spotkań TC39 i muszą zostać zatwierdzone przez cały komitet, zanim staną się oficjalne. W przypadku Array.prototype.flatten propozycja przeszła już kilka etapów uzgodnień, aż do etapu 3, co oznacza, że funkcja jest gotowa do wdrożenia w przeglądarkach internetowych. Podczas wdrażania często pojawiają się dodatkowe problemy ze specyfikacją. W tym przypadku najważniejsze opinie otrzymaliśmy po wdrożenie tej funkcji: w jej obecnej formie funkcja ta powoduje błędy w sieci. Trudne do przewidzenia problemy, takie jak te, są jednym z powodów, dla których proces TC39 nie kończy się wraz z wdrożeniem funkcji przez przeglądarki.

TC39 działa na zasadzie konsensusu, co oznacza, że komitet musi wyrazić zgodę na wszelkie nowe zmiany. Nawet jeśli smoosh była poważną propozycją, wydaje się prawdopodobne, że członek komitetu sprzeciwi się jej na rzecz bardziej powszechnej nazwy, takiej jak compact lub chain.

Zmiana nazwy z flatten na smoosh (nawet jeśli nie była to żart) nigdy nie była omawiana na spotkaniu TC39. Dlatego oficjalne stanowisko TC39 w tej sprawie jest obecnie nieznane. Dopóki nie osiągniemy konsensusu na kolejnym spotkaniu, nikt nie może wypowiadać się w imieniu całego komitetu TC39.

W spotkaniach TC39 zazwyczaj uczestniczą osoby o bardzo zróżnicowanym doświadczeniu: niektórzy mają wieloletnie doświadczenie w projektowaniu języków programowania, inni pracują nad przeglądarką lub silnikiem JavaScript, a coraz więcej osób reprezentuje społeczność programistów JavaScript.

Jak rozwiązano problem SmooshGate?

Podczas spotkania TC39 w maju 2018 r. problem #SmooshGate został oficjalnie rozwiązany przez zmianę nazwy flatten na flat.

Array.prototype.flatArray.prototype.flatMap zostały udostępnione w V8 6.9 i Chrome 69.