Co się stało z smoosh?
Okazuje się, że propozycja funkcji języka JavaScript o nazwie Array.prototype.flatten
jest 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 wielu innych witryn. (Chociaż w 2018 roku narzędzie MooTools nie było powszechnie wykorzystywane w przypadku nowych witryn, to w przeszłości cieszyło się ono dużą popularnością i nadal jest dostępne na wielu stronach produkcyjnych).
Autor propozycji zaproponował żartobliwie, że aby uniknąć problemów ze zgodnością, należy 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 robi MooTools, 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.
Idzie Ci doskonale!
Niestety, dzieje się coś innego. MooNarzędzia kopiuje wszystkie niestandardowe metody tablic do narzędzia Elements.prototype
(gdzie Elements
to interfejs API 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 wysyłają natywną wersję interfejsu flatten
, staje się ona niewyliczana i nie jest kopiowana do Elements
. Każdy kod korzystający z biblioteki MooToolsElements.prototype.flatten
jest teraz uszkodzony.
Zmiana natywną Array.prototype.flatten
na wyliczaną rozwiązała problem, ale prawdopodobnie spowoduje jeszcze większe problemy 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 tu modyfikacja obiektów wbudowanych. Rozszerzanie prototypów natywnych jest obecnie ogólnie uważane 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 ktoś pracował nad tą witryną przez wszystkie lata, aktualizując ją za każdym razem, gdy dostawcy przeglądarek udostępniali 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, którzy wysyłają nową funkcję, tracą udział w rynku, ponieważ użytkownicy zmieniają przeglądarkę po zauważeniu, że działa ona 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, a użytkownicy będą mogli nadal korzystać z Internetu. Wybór jest prosty.
Czy to oznacza, że złych interfejsów API nie można nigdy usunąć z platformy internetowej?
To zależy. W rzadkich przypadkach nieprawidłowe funkcje mogą zostać usunięte z sieci WWW. 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 poprawiamy po prostu narzędzi MooTools?
Dobrym pomysłem jest wdrożenie poprawki w 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 platforma MooTools publikowała poprawkę, a każda witryna korzystająca z narzędzi Moo Tools została w magicznie zaktualizowana następnego dnia. 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 zajęłby w najlepszym razie lata.
Pamiętaj, że wiele z tych witryn jest starych i prawdopodobnie nie jest już aktualizowanych. Nawet jeśli osoba ta nadal pracuje w Twojej firmie, 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 działa proces TC39?
TC39 to komitet odpowiedzialny za ulepszanie języka JavaScript za pomocą standardu ECMAScript.
#SmooshGate sprawił, że niektórzy użytkownicy uwierzyli, że „TC39 chce zmienić nazwę flatten
na smoosh
”. Była to jednak wewnętrzna żartobliwa nazwa, która nie została dobrze zakomunikowana na zewnątrz.
Ważne decyzje, takie jak zmiana nazwy oferty, nie są podejmowane
przez jedną osobę i na pewno nie są podejmowane z dnia na dzień po jednym komentarzu w 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. Takie trudne do przewidzenia problemy to jeden z powodów, dla których proces TC39 nie kończy się tylko po udostępnieniu funkcji przez przeglądarki.
TC39 opiera się na konsensusie, co oznacza, że komisja musi uzgodnić wszelkie nowe zmiany. Nawet jeśli smoosh
to poważna propozycja, 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 ostatecznie rozwiązano SmooshGate?
Podczas spotkania TC39 w maju 2018 r. problem #SmooshGate został oficjalnie rozwiązany przez zmianę nazwy flatten
na flat
.
Array.prototype.flat
i Array.prototype.flatMap
zostały udostępnione w V8 6.9 i Chrome 69.