Questions fréquentes sur SmooshGate

Que s'est-il passé ?

Une proposition de fonctionnalité du langage JavaScript appelée Array.prototype.flatten n'est pas compatible avec le Web. L'ajout de la fonctionnalité dans Firefox Nightly a entraîné le dysfonctionnement d'au moins un site Web populaire. Étant donné que le code problématique fait partie de la bibliothèque MooTools, il est probable que de nombreux autres sites Web soient affecté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.)

En plaisantant, l'auteur de la proposition a suggéré de renommer flatten en smoosh pour éviter le problème de compatibilité. La blague n'était pas claire pour tout le monde, certaines personnes ont commencé à croire à tort que le nouveau nom avait déjà été décidé, et les choses s'aggravent rapidement.

Que fait Array.prototype.flatten ?

Array.prototype.flat, initialement proposé sous la forme Array.prototype.flatten, aplatit les tableaux de manière récursive jusqu'à la valeur depth spécifiée, définie par défaut sur 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, sauf qu'elle aplatit le résultat dans un nouveau tableau.

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

Que fait MooTools qui est à l'origine de 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 de MooTools diffère de la norme proposée. Cependant, ce n'est pas le problème ! Lorsque les navigateurs fournissent des Array.prototype.flatten de manière native, MooTools remplace l'implémentation native. Cela garantit que le code qui s'appuie sur le comportement de MooTools fonctionne comme prévu, que l'élément flatten natif soit disponible ou non. Aucun problème pour le moment !

Malheureusement, autre chose se produit ensuite. MooTools copie toutes ses méthodes de tableau personnalisé 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 effectue une itération sur les propriétés "énumérables", qui n'incluent pas de méthodes natives telles que Array.prototype.sort, mais qui incluent des propriétés régulièrement attribuées telles que Array.prototype.foo = whatever. Toutefois, si vous écrasez une propriété non énumérable, par exemple Array.prototype.sort = whatever, elle le reste.

Actuellement, Array.prototype.flatten = mooToolsFlattenImplementation crée une propriété flatten énumérable. Elle est donc ensuite copiée dans Elements. Toutefois, si les navigateurs fournissent une version native de flatten, celle-ci n'est plus énumérable et n'est pas copiée dans Elements. Tout code qui dépend de la méthode Elements.prototype.flatten de MooTools ne fonctionne plus.

Bien qu'il semble que le fait de modifier le Array.prototype.flatten natif de sorte qu'il soit énumérable permette de résoudre le problème, cela causerait probablement encore plus de problèmes de compatibilité. Chaque site Web qui s'appuie sur for-in pour itérer un tableau (ce qui est une mauvaise pratique, mais cela se produit) obtiendrait soudainement une itération de boucle supplémentaire pour la propriété flatten.

Le problème sous-jacent le plus important est la modification des objets intégrés. L'extension des prototypes natifs est généralement acceptée comme une mauvaise pratique de nos jours, car elle n'est pas adaptée aux autres bibliothèques et au code tiers. Ne modifiez pas les objets qui ne vous appartiennent pas.

Pourquoi ne pas simplement conserver le nom existant et briser le Web ?

En 1996, avant que les CSS ne se généralisent et bien avant que le HTML5 ne devienne un évènement, le site Web Space Jam a été lancé. Aujourd'hui, le site web fonctionne toujours comme il y a 22 ans.

Comment cela s'est-il produit ? Quelqu'un a-t-il entretenu ce site Web pendant toutes ces années, en le mettant à jour chaque fois que les fournisseurs de navigateurs lançaient une nouvelle fonctionnalité ?

Il s'avère que "n'interrompez pas le Web" est le premier principe de conception pour HTML, CSS, JavaScript et toute autre norme largement utilisée sur le Web. Si l'ajout d'une nouvelle fonctionnalité dans le navigateur entraîne l'arrêt des sites Web existants, tout le monde ne peut pas:

  • les visiteurs des sites Web affectés ont soudainement une expérience utilisateur défaillante ;
  • les propriétaires de sites Web sont passés d’un site web parfaitement fonctionnel à un site non fonctionnel sans rien changer ;
  • les fournisseurs de navigateurs qui proposent cette nouvelle fonctionnalité perdent des parts de marché, car les utilisateurs changent de navigateur après avoir constaté qu'elle fonctionne dans le navigateur X.
  • une fois le problème de compatibilité connu, d'autres fournisseurs de navigateurs refusent de le proposer. La spécification de la caractéristique ne correspond pas à la réalité (rien qu'une œuvre de fiction), ce qui est nuisible au processus de standardisation.

Rétrospectivement, MooTools n'a pas fait ce qu'il faut, mais briser le Web ne le punira pas, mais punira les utilisateurs. Ces utilisateurs ne savent pas ce qu'est un outil Moo. Nous pouvons également trouver une autre solution pour que les utilisateurs puissent continuer à naviguer sur le Web. Le choix est facile à faire.

Cela signifie-t-il que les API incorrectes ne pourront jamais être supprimées de la plate-forme Web ?

Cela dépend. Dans de rares cas, des fonctionnalités erronées peuvent être supprimées du Web. Le simple fait de déterminer s'il est possible de supprimer une caractéristique est un effort très délicat, qui nécessite une télémétrie approfondie pour quantifier le nombre de pages Web dont le comportement aurait été modifié. Toutefois, une telle fonctionnalité peut être utilisée si elle n'est pas suffisamment sécurisée, si elle est dangereuse pour les utilisateurs ou si elle est très rarement utilisée.

<applet>, <keygen> et showModalDialog() sont tous des exemples d'API incorrectes qui ont bien été supprimées de la plate-forme Web.

Pourquoi ne pas simplement régler MooTools ?

Il est recommandé d'appliquer des correctifs à MooTools pour ne plus étendre les objets intégrés. Toutefois, cela ne résout pas le problème en question. Même si MooTools publiait une version corrigée, tous les sites Web existants qui l'utilisaient devront être mis à jour pour que le problème de compatibilité disparaisse.

Ne peut-il pas simplement mettre à jour sa copie de MooTools ?

Dans un monde parfait, MooTools publierait un correctif, et chaque site Web utilisant MooTools serait automatiquement mis à jour le lendemain. Problème résolu, n'est-ce pas ?

Malheureusement, ce n'est pas réaliste. Même si quelqu'un devait identifier l'ensemble des sites Web concernés, trouver les coordonnées de chacun d'entre eux, contacter avec succès tous les propriétaires de sites Web et les convaincre tous d'effectuer la mise à jour (ce qui peut impliquer de refactoriser l'intégralité de leur code base), l'ensemble du processus prendra, au mieux, des années.

Gardez à l'esprit que bon nombre de ces sites Web sont anciens et probablement peu entretenus. Même si celui-ci est toujours en ligne, 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 change son site Web vieux de 8 ans en raison d'un problème de compatibilité Web.

Comment fonctionne le processus TC39 ?

TC39 est le comité chargé de faire évoluer le langage JavaScript via la norme ECMAScript.

#SmooshGate a fait croire à certains que "TC39 veut renommer flatten en smoosh", mais il s'agissait d'une blague qui n'a pas été bien communiquée en externe. Les décisions majeures telles que le changement de nom d'une proposition ne sont pas prises à la légère, ne sont pas prises par une seule personne et ne sont pas prises du jour au lendemain sur la base d'un seul commentaire GitHub.

TC39 applique un processus de préproduction clair pour les propositions de fonctionnalités. Les propositions d'ECMAScript et toute modification majeure qui leur est apportée (y compris le changement de nom de méthode) sont abordés lors des réunions 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à franchi plusieurs étapes d'accord, jusqu'à l'étape 3, indiquant que la fonctionnalité est prête à être implémentée dans les navigateurs Web. Il est courant que d'autres problèmes de spécifications surviennent lors de la mise en œuvre. Dans ce cas, le commentaire le plus important est apparu après la tentative de livraison: la fonctionnalité, dans son état actuel, interrompt le Web. Ce type de problème difficile à prévoir explique en partie pourquoi le processus TC39 ne se termine pas seulement une fois que les navigateurs proposent une fonctionnalité.

Le TC39 fonctionne sur consensus, ce qui signifie que le comité doit se mettre d'accord sur toute nouvelle modification. Même si smoosh était une suggestion sérieuse, il semble probable qu'un membre du comité s'y oppose 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 fait l'objet d'une discussion lors d'une réunion TC39. Par conséquent, la position officielle de TC39 sur ce sujet est actuellement inconnue. Aucune personne ne peut s'exprimer au nom de l'ensemble des TC 39 tant qu'un consensus n'est pas trouvé lors de la prochaine réunion.

Les réunions TC39 sont généralement suivies par des personnes aux parcours très variés: 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 présents pour représenter la communauté des développeurs JavaScript.

Comment SmooshGate a-t-il finalement été résolu ?

Lors de la réunion TC39 de mai 2018, #SmooshGate a été officiellement résolu en renommant flatten flat.

Array.prototype.flat et Array.prototype.flatMap sont disponibles dans les versions V8 v6.9 et Chrome 69.