Domande frequenti su SmooshGate

Che smoosh è successo?

Una proposta per una funzionalità del linguaggio JavaScript chiamata Array.prototype.flatten risulta essere incompatibile con il web. Il rilascio della funzionalità in Firefox Nightly ha causato il malfunzionamento di almeno un sito web popolare. Dato che il codice problematico fa parte della biblioteca MooTools molto diffusa, è probabile che siano interessati molti altri siti web. Anche se nel 2018 MooTools non è comunemente utilizzato per i nuovi siti web, in passato era molto popolare ed è ancora presente su molti siti web di produzione.

L'autore della proposta ha suggerito scherzosamente di rinominare flatten in smoosh per evitare il problema di compatibilità. La battuta non era chiara a tutti, alcune persone hanno iniziato a credere erroneamente che il nuovo nome fosse già stato deciso e la situazione è peggiorata rapidamente.

Che cosa fa Array.prototype.flatten?

Array.prototype.flat, inizialmente proposto come Array.prototype.flatten, appiattisce gli array in modo ricorsivo fino al valore depth specificato, che per impostazione predefinita è 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]

La stessa proposta include Array.prototype.flatMap, che è simile a Array.prototype.map, tranne per il fatto che appiattisce il risultato in un nuovo array.

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

Cosa fa MooTools che causa questo problema?

MooTools definisce la propria versione non standard di Array.prototype.flatten:

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

L'implementazione di flatten di MooTools è diversa dallo standard proposto. Tuttavia, non è questo il problema. Quando i browser supportano Array.prototype.flatten in modo nativo, MooTools sostituisce l'implementazione nativa. In questo modo, il codice che si basa sul comportamento di MooTools funziona come previsto, indipendentemente dal fatto che flatten nativo sia disponibile. Finora stai andando bene.

Purtroppo, accade qualcos\'altro. MooTools copia tutti i suoi metodi di array personalizzati in Elements.prototype (dove Elements è un'API specifica di MooTools):

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

for-in esegue l'iterazione sulle proprietà "enumerabili", che non include metodi nativi come Array.prototype.sort, ma include proprietà assegnate regolarmente come Array.prototype.foo = whatever. Tuttavia, e qui sta il bello, se sovrascrivi una proprietà non enumerabile, ad esempio Array.prototype.sort = whatever, questa rimane non enumerabile.

Al momento, Array.prototype.flatten = mooToolsFlattenImplementation crea una proprietà flatten enumerabile, quindi viene copiata in un secondo momento in Elements. Tuttavia, se i browser forniscono una versione nativa di flatten, questa diventa non enumerabile e non viene copiata in Elements. Qualsiasi codice che si basa su MooToolsElements.prototype.flatten ora non funziona più.

Sebbene sembri che la modifica di Array.prototype.flatten nativo in modo che sia enumerabile risolva il problema, probabilmente causerebbe ancora più problemi di compatibilità. Ogni sito web che si basa su for-in per eseguire l'iterazione su una matrice (una cattiva pratica, ma capita) riceverebbe improvvisamente un'iterazione del loop aggiuntiva per la proprietà flatten.

Il problema più grande sottostante è la modifica degli oggetti incorporati. L'estensione purosangue è generalmente accettata come una cattiva prassi al giorno d'oggi, poiché non si combina bene con altre librerie e codice di terze parti. Non modificare gli oggetti di cui non sei proprietario.

Perché non mantenere il nome esistente e rompere il web?

Nel 1996, prima che il CSS diventasse di uso comune e molto prima che l'HTML5 diventasse una realtà, è stato lanciato il sito web di Space Jam. Oggi il sito web funziona ancora allo stesso modo di 22 anni fa.

Come è successo? Qualcuno ha gestito questo sito web per tutti questi anni, aggiornandolo ogni volta che i fornitori di browser hanno rilasciato una nuova funzionalità?

A quanto pare, "non rompere il web" è il principio di progettazione più importante per HTML, CSS, JavaScript e qualsiasi altro standard ampiamente utilizzato sul web. Se il lancio di una nuova funzionalità del browser causa l'interruzione del funzionamento dei siti web esistenti, è un problema per tutti:

  • i visitatori dei siti web interessati improvvisamente non riescono più a usufruire dell'esperienza utente;
  • i proprietari del sito web sono passati da un sito perfettamente funzionante a uno non funzionale senza apportare modifiche.
  • i fornitori di browser che implementano la nuova funzionalità perdono quote di mercato, poiché gli utenti cambiano browser dopo aver notato che "funziona nel browser X".
  • Una volta noto il problema di compatibilità, gli altri fornitori di browser si rifiutano di implementarlo. La specifica della funzionalità non corrisponde alla realtà (non è altro che una finzione), il che è negativo per il processo di standardizzazione.

Certo, a posteriori MooTools ha fatto la cosa sbagliata, ma non è stato punito per aver danneggiato il web, bensì gli utenti. Questi utenti non sanno che cos'è un moo tool. In alternativa, possiamo trovare un'altra soluzione e gli utenti possono continuare a utilizzare il web. La scelta è facile.

Ciò significa che le API non valide non possono mai essere rimosse dalla piattaforma web?

Dipende. In rari casi, le funzionalità dannose possono essere rimosse dal web. Anche solo capire se è possibile rimuovere una funzionalità è un'operazione molto complessa, che richiede una telemetria estesa per quantificare il numero di pagine web di cui cambierebbe il comportamento. Tuttavia, quando la funzionalità non è sufficientemente sicura, è dannosa per gli utenti o viene utilizzata molto raramente, è possibile farlo.

<applet>, <keygen> e showModalDialog() sono tutti esempi di API non valide che sono state rimosse correttamente dalla piattaforma web.

Perché non correggere semplicemente MooTools?

È una buona idea applicare una patch a MooTools in modo che non espanda più gli oggetti incorporati. Tuttavia, non risolve il problema in questione. Anche se MooTools dovesse rilasciare una versione con patch, tutti i siti web esistenti che la utilizzano dovrebbero essere aggiornati per risolvere il problema di compatibilità.

Non possono semplicemente aggiornare la propria copia di MooTools?

In un mondo perfetto, MooTools rilascerebbe una patch e ogni singolo sito web che utilizza MooTools verrebbe magicamente aggiornato il giorno successivo. Problema risolto, giusto?!

Purtroppo, non è realistico. Anche se qualcuno riuscisse a identificare in qualche modo l'insieme completo dei siti web interessati, a trovare i dati di contatto di ciascuno di essi, a contattare tutti i proprietari dei siti web e convincerli tutti a eseguire l'aggiornamento (il che potrebbe comportare il refactoring dell'intera base di codice), l'intera procedura richiederebbe anni, nella migliore delle ipotesi.

Tieni presente che molti di questi siti web sono vecchi e probabilmente non vengono più gestiti. Anche se il maintainer è ancora disponibile, è possibile che non sia un sviluppatore web altamente qualificato come te. Non possiamo aspettarci che tutti cambino il proprio sito web di 8 anni a causa di un problema di compatibilità web.

Come funziona il processo TC39?

TC39 è il comitato incaricato di far evolvere il linguaggio JavaScript tramite lo standard ECMAScript.

#SmooshGate ha portato alcuni a pensare che "il TC39 vuole rinominare flatten in smoosh", ma si trattava di una barzelletta interna che non è stata comunicata bene all'esterno. Le decisioni importanti, come la ridenominazione di una proposta, non vengono prese alla leggera, non vengono prese da una sola persona e sicuramente non vengono prese dall'oggi al domani in base a un singolo commento di GitHub.

Il TC39 adotta una procedura di staging chiara per le proposte di funzionalità. Le proposte ECMAScript e le eventuali modifiche sostanziali (inclusa la ridenominazione dei metodi) vengono discusse durante le riunioni del TC39 e devono essere approvate dall'intero comitato prima di diventare ufficiali. Nel caso di Array.prototype.flatten, la proposta ha già attraversato diversi livelli di accordo, fino alla Fase 3, il che indica che la funzionalità è pronta per essere implementata nei browser web. È normale che si verifichino ulteriori problemi relativi alle specifiche durante l'implementazione. In questo caso, il feedback più importante è arrivato dopo aver provato a implementare la funzionalità: al suo stato attuale, la funzionalità interrompe il web. Problemi difficili da prevedere come questi sono uno dei motivi per cui la procedura TC39 non termina quando i browser implementano una funzionalità.

Il TC39 opera per consenso, il che significa che il comitato deve essere d'accordo su eventuali nuove modifiche. Anche se smoosh fosse stato un suggerimento serio, è probabile che un membro del comitato obietti in favore di un nome più comune come compact o chain.

La ridenominazione da flatten a smoosh (anche se non fosse stata una barzelletta) non è mai stata discussa in una riunione del TC39. Pertanto, la posizione ufficiale del TC39 su questo argomento è attualmente sconosciuta. Nessun singolo individuo può parlare per conto di tutto il TC39 finché non viene raggiunto il consenso nella riunione successiva.

Alle riunioni del TC39 partecipano generalmente persone con background molto diversi: alcune hanno anni di esperienza nella progettazione di linguaggi di programmazione, altre lavorano su un browser o un motore JavaScript e un numero crescente di partecipanti rappresenta la community di sviluppatori JavaScript.

Come è stato risolto SmooshGate?

Durante la riunione del TC39 di maggio 2018, il problema #SmooshGate è stato risolto ufficialmente rinominando flatten in flat.

Array.prototype.flat e Array.prototype.flatMap sono stati rilasciati in V8 6.9 e Chrome 69.