Cosa è successo basso?!
Una proposta per una funzionalità in linguaggio JavaScript chiamata Array.prototype.flatten
si rivela incompatibile con il web. La spedizione della funzionalità in Firefox Nightly ha causato l'interruzione 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, questo non è il problema. Quando i browser inviano 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 includono metodi nativi come Array.prototype.sort
, ma includono proprietà assegnate regolarmente come Array.prototype.foo = whatever
. Tuttavia,
ed ecco l'occhiello, se sovrascrivi una proprietà non enumerabile, ad esempio
Array.prototype.sort = whatever
, 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 inviano una versione nativa di flatten
, questa non è enumerabile e
non viene copiata in Elements
. Qualsiasi codice basato su MooTools
Elements.prototype.flatten
ora non funziona.
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 ciclo 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 il sito per tutti questi anni, aggiornandolo ogni volta che i fornitori di browser lanciavano una nuova funzione?
È emerso che "non interrompere il web" è il principio di progettazione principale 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 subiscono improvvisamente un'esperienza utente non funzionante;
- i proprietari del sito web sono passati da un sito perfettamente funzionante a uno non funzionale senza apportare modifiche.
- i fornitori di browser che offrono la nuova funzionalità perdono quota di mercato a causa del passaggio da un browser all'altro dopo aver notato che "funziona con il 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 rompere il web non li punisce, punisce gli utenti. Questi utenti non sanno cosa sia uno strumento moo. 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 difficile, richiedere una telemetria estesa per quantificare quante pagine web avrebbero il loro comportamento cambiato. Tuttavia, se 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 rimosse dalla piattaforma web.
Perché non correggiamo solo MooTools?
È consigliabile applicare patch a MooTools in modo che non estenda più gli oggetti integrati. Tuttavia, non risolve il problema in questione. Anche se MooTools rilascesse una versione con patch, tutti i siti web esistenti che la utilizzano dovrebbero eseguire l'aggiornamento 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 in qualche modo a identificare 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 obsoleti e probabilmente non vengono mantenuti. Anche se il gestore è ancora disponibile, è possibile che non sia uno 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 un'invenzione 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 di ECMAScript e le relative modifiche sostanziali (compresa 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à superato diverse
fasi di approvazione, 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 il processo TC39 non termina solo con la fornitura di una funzionalità da parte dei browser.
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 per non fosse stato uno scherzo)
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 a nome
di tutto il TC39 finché non si raggiunge un accordo nella prossima riunione.
Le riunioni del TC39 sono generalmente partecipate da persone con background molto diversificati: 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 degli 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 disponibili con V8 v6.9 e
Chrome 69.