Qu'est-ce qui s'est passé ?
Une proposition pour une fonctionnalité de langage JavaScript appelée Array.prototype.flatten
s'avère incompatible avec le Web. Le déploiement de la fonctionnalité dans Firefox Nightly a entraîné la défaillance d'au moins un site Web populaire. Étant donné que le code problématique fait partie de la bibliothèque MooTools très répandue, il est probable que de nombreux autres sites Web soient concernés. (Bien que MooTools ne soit pas couramment utilisé pour les nouveaux sites Web en 2018, il était très populaire et est toujours présent sur de nombreux sites Web de production.)
L'auteur de la proposition a suggéré, en plaisantant, de renommer flatten
en smoosh
pour éviter le problème de compatibilité. La blague n'était pas claire pour tout le monde. Certains ont commencé à croire à tort que le nouveau nom avait déjà été décidé, et les choses ont rapidement dégénéré.
À quoi sert Array.prototype.flatten
?
Array.prototype.flat
, initialement proposé sous le nom de Array.prototype.flatten
, aplatit les tableaux de manière récursive jusqu'à la valeur depth
spécifiée, qui est par défaut 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 même proposition inclut Array.prototype.flatMap
, qui est semblable à Array.prototype.map
, mais qui aplatit le résultat dans un nouveau tableau.
[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]
Qu'est-ce que MooTools fait pour causer ce problème ?
MooTools définit sa propre version non standard de Array.prototype.flatten
:
Array.prototype.flatten = /* non-standard implementation */;
L'implémentation de flatten
dans MooTools diffère de la norme proposée.
Cependant, ce n'est pas le problème. Lorsque les navigateurs fournissent Array.prototype.flatten
de manière native, MooTools remplace l'implémentation native. Cela garantit que le code qui s'appuie sur le comportement MooTools fonctionne comme prévu, que flatten
natif soit disponible ou non.
Aucun problème pour le moment !
Malheureusement, un autre problème se produit. MooTools copie toutes ses méthodes de tableau personnalisées dans Elements.prototype
(où Elements
est une API spécifique à MooTools):
for (var key in Array.prototype) {
Elements.prototype[key] = Array.prototype[key];
}
for
-in
itère sur les propriétés "énumérables", qui n'incluent pas les méthodes natives telles que Array.prototype.sort
, mais incluent les propriétés régulièrement attribuées telles que Array.prototype.foo = whatever
. Mais, et c'est là le point crucial, si vous écrasez une propriété non énumérable, par exemple Array.prototype.sort = whatever
, elle reste non énumérable.
Actuellement, Array.prototype.flatten = mooToolsFlattenImplementation
crée une propriété flatten
énumérable, qui est ensuite copiée dans Elements
. Toutefois, si les navigateurs fournissent une version native de flatten
, elle devient non énumérable et n'est pas copiée dans Elements
. Tout code reposant sur Elements.prototype.flatten
de MooTools est désormais défectueux.
Bien qu'il semble que la modification de la Array.prototype.flatten
native pour qu'elle soit énumérable résolve le problème, cela entraînerait probablement encore plus de problèmes de compatibilité. Chaque site Web qui s'appuie sur for
-in
pour itérer sur un tableau (ce qui est une mauvaise pratique, mais cela arrive) recevrait alors soudainement une itération de boucle supplémentaire pour la propriété flatten
.
Le plus gros problème sous-jacent est la modification d'objets intégrés. L'extension des prototypes natifs est généralement considérée comme une mauvaise pratique de nos jours, car elle ne se compose pas bien avec d'autres bibliothèques et du code tiers. Ne modifiez pas les objets dont vous n'êtes pas le propriétaire.
Pourquoi ne pas simplement conserver le nom existant et casser le Web ?
En 1996, avant que le CSS ne devienne répandu et bien avant que le "HTML5" ne soit une réalité, le site Web de Space Jam a été mis en ligne. Aujourd'hui, le site Web fonctionne toujours de la même manière qu'il y a 22 ans.
Comment cela s'est-il passé ? Quelqu'un a-t-il géré ce site Web pendant toutes ces années, en le mettant à jour chaque fois que les fournisseurs de navigateurs ont lancé une nouvelle fonctionnalité ?
Il s'avère que "ne pas casser le Web" est le principe de conception numéro 1 pour HTML, CSS, JavaScript et toute autre norme largement utilisée sur le Web. Si le lancement d'une nouvelle fonctionnalité de navigateur entraîne l'arrêt du fonctionnement des sites Web existants, cela est défavorable pour tous:
- l'expérience utilisateur des visiteurs des sites Web concernés est soudainement interrompue ;
- le site Web des propriétaires est passé d'un site parfaitement fonctionnel à un site non fonctionnel sans qu'ils n'aient rien changé ;
- les fournisseurs de navigateurs qui proposent la nouvelle fonctionnalité perdent de la part de marché, car les utilisateurs changent de navigateur après avoir constaté qu'il fonctionne dans le navigateur X ;
- Une fois le problème de compatibilité connu, les autres fournisseurs de navigateurs refusent de le distribuer. La spécification de la fonctionnalité ne correspond pas à la réalité ("rien d'autre qu'un travail de fiction"), ce qui est mauvais pour le processus de normalisation.
Certes, rétrospectivement, MooTools a fait ce qu'il ne fallait pas. Mais ce n'est pas la punition qui les intéresse, mais celle des utilisateurs. Ces utilisateurs ne savent pas ce qu'est un outil MOO. Nous pouvons également trouver une autre solution, et les utilisateurs peuvent continuer à utiliser le Web. Le choix est facile.
Cela signifie-t-il que les API défectueuses ne peuvent jamais être supprimées de la plate-forme Web ?
Cela dépend. Dans de rares cas, des fonctionnalités incorrectes peuvent être supprimées du Web. Même déterminer s'il est possible de supprimer une fonctionnalité est une tâche très délicate, qui nécessite une télémétrie étendue pour quantifier le nombre de pages Web dont le comportement serait modifié. Toutefois, lorsque la fonctionnalité est suffisamment peu sécurisée, est nuisible aux utilisateurs ou est utilisée très rarement, cela peut être fait.
<applet>
, <keygen>
et showModalDialog()
sont tous des exemples d'API défectueuses qui ont été supprimées de la plate-forme Web.
Pourquoi ne pas simplement corriger MooTools ?
Il est judicieux de corriger MooTools afin qu'il n'étende plus les objets intégrés. Cependant, cela ne résout pas le problème en question. Même si MooTools publiait une version avec correctif, tous les sites Web existants qui l'utilisent devraient être mis à jour pour que le problème de compatibilité disparaisse.
Les utilisateurs ne peuvent-ils pas simplement mettre à jour leur copie de MooTools ?
Dans un monde idéal, MooTools publierait un correctif et chaque site Web utilisant MooTools serait mis à jour comme par magie le lendemain. Problème résolu, n'est-ce pas ?
Malheureusement, ce n'est pas réaliste. Même si quelqu'un parvenait à identifier l'ensemble des sites Web concernés, à trouver les coordonnées de chacun d'eux, à contacter tous les propriétaires de sites Web et à les convaincre de procéder à la mise à jour (ce qui pourrait impliquer de refactoriser l'intégralité de leur base de code), l'ensemble du processus prendrait des années, au mieux.
Gardez à l'esprit que de nombreux sites Web de ce type sont anciens et probablement non entretenus. Même si le mainteneur est toujours là, il est possible qu'il ne soit pas un développeur Web hautement qualifié comme vous. Nous ne pouvons pas nous attendre à ce que tout le monde modifie son site Web vieux de huit ans en raison d'un problème de compatibilité Web.
Comment fonctionne le processus TC39 ?
Le TC39 est le comité chargé de l'évolution du langage JavaScript via la norme ECMAScript.
Le #SmooshGate a conduit certains à penser que le TC39 voulait renommer flatten
en smoosh
, mais il s'agissait d'une blague interne qui n'a pas été bien communiquée en externe.
Les décisions importantes, comme le renommage d'une proposition, ne sont pas prises à la légère, ne sont pas prises par une seule personne et ne sont certainement pas prises du jour au lendemain en fonction d'un seul commentaire GitHub.
Le TC39 applique un processus de préproduction clair pour les propositions de fonctionnalités.
Les propositions ECMAScript et les modifications majeures apportées à celles-ci (y compris le renommage de méthode) sont discutées lors des réunions du TC39 et doivent être approuvées par l'ensemble du comité avant de devenir officielles. Dans le cas de Array.prototype.flatten
, la proposition a déjà passé plusieurs étapes d'accord, jusqu'à l'étape 3, ce qui indique que la fonctionnalité est prête à être implémentée dans les navigateurs Web. Il est courant que des problèmes de spécification supplémentaires surviennent lors de l'implémentation. Dans ce cas, les commentaires les plus importants sont arrivés après avoir essayé de la déployer: la fonctionnalité, dans son état actuel, interrompt le Web. Ces problèmes difficiles à prévoir sont l'une des raisons pour lesquelles le processus TC39 ne se termine pas une fois que les navigateurs ont publié une fonctionnalité.
Le TC39 fonctionne sur la base du consensus, ce qui signifie que le comité doit être d'accord sur toute nouvelle modification. Même si smoosh
avait été une suggestion sérieuse, il semble probable qu'un membre du comité s'y opposerait en faveur d'un nom plus courant comme compact
ou chain
.
Le changement de nom de flatten
en smoosh
(même s'il ne s'agissait pas d'une blague) n'a jamais été discuté lors d'une réunion du TC39. Par conséquent, la position officielle du TC39 sur ce sujet est actuellement inconnue. Aucune personne ne peut parler au nom de l'ensemble du TC39 tant qu'un consensus n'est pas atteint lors de la prochaine réunion.
Les réunions du TC39 sont généralement fréquentées par des personnes aux parcours très divers: certaines ont des années d'expérience en conception de langages de programmation, d'autres travaillent sur un navigateur ou un moteur JavaScript, et un nombre croissant de participants sont là pour représenter la communauté des développeurs JavaScript.
Comment le SmooshGate a-t-il été résolu ?
Lors de la réunion TC39 de mai 2018, le #SmooshGate a été officiellement résolu en renommant flatten
en flat
.
Array.prototype.flat
et Array.prototype.flatMap
sont fournis dans V8 v6.9 et Chrome 69.