Veelgestelde vragen over SmooshGate

Wat is er gebeurd?!

Een voorstel voor een JavaScript-taalfunctie genaamd Array.prototype.flatten blijkt web-incompatibel te zijn. Het verzenden van de functie in Firefox Nightly zorgde ervoor dat ten minste één populaire website kapot ging. Gezien het feit dat de problematische code deel uitmaakt van de wijdverspreide MooTools-bibliotheek, is het waarschijnlijk dat nog veel meer websites hierdoor getroffen worden. (Hoewel MooTools in 2018 niet vaak wordt gebruikt voor nieuwe websites, was het vroeger erg populair en is het nog steeds aanwezig op veel productiewebsites.)

De auteur van het voorstel stelde gekscherend voor om flatten te hernoemen naar smoosh om compatibiliteitsproblemen te voorkomen. De grap was niet voor iedereen duidelijk, sommige mensen begonnen ten onrechte te geloven dat de nieuwe naam al was besloten, en de zaken escaleerden snel.

Wat doet Array.prototype.flatten ?

Array.prototype.flat , oorspronkelijk voorgesteld als Array.prototype.flatten , vlakt arrays recursief af tot de opgegeven depth , die standaard op 1 staat .

// 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]

Hetzelfde voorstel omvat Array.prototype.flatMap , wat lijkt op Array.prototype.map , behalve dat het het resultaat afvlakt tot een nieuwe array.

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

Wat doet MooTools dat dit probleem veroorzaakt?

MooTools definieert hun eigen niet-standaardversie van Array.prototype.flatten :

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

flatten -implementatie van MooTools wijkt af van de voorgestelde standaard. Dit is echter niet het probleem! Wanneer browsers Array.prototype.flatten native verzenden, overschrijft MooTools de native implementatie. Dit zorgt ervoor dat code die afhankelijk is van het MooTools-gedrag werkt zoals bedoeld, ongeacht of native flatten beschikbaar is. Tot nu toe, zo goed!

Helaas gebeurt er dan iets anders. MooTools kopieert al zijn aangepaste arraymethoden naar Elements.prototype (waar Elements een MooTools-specifieke API is):

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

for - in itereert over “optelbare” eigenschappen, die geen native methoden zoals Array.prototype.sort bevatten, maar wel regelmatig toegewezen eigenschappen zoals Array.prototype.foo = whatever . Maar – en hier is het belangrijkste – als je een niet-opsombare eigenschap overschrijft, bijvoorbeeld Array.prototype.sort = whatever , blijft deze niet-opsombaar.

Momenteel creëert Array.prototype.flatten = mooToolsFlattenImplementation een opsombare eigenschap flatten , zodat deze later naar Elements wordt gekopieerd. Maar als browsers een native versie van flatten leveren, wordt deze niet meer opsombaar en wordt deze niet naar Elements gekopieerd. Elke code die afhankelijk is van Elements.prototype.flatten van MooTools is nu kapot.

Hoewel het erop lijkt dat het veranderen van de oorspronkelijke Array.prototype.flatten zodat deze opsombaar is, het probleem zou oplossen, zou dit waarschijnlijk zelfs nog meer compatibiliteitsproblemen veroorzaken. Elke website die vertrouwt op for - in om over een array te itereren (wat een slechte gewoonte is, maar het gebeurt) zou dan plotseling een extra lus-iteratie krijgen voor de flatten eigenschap.

Het grotere onderliggende probleem hier is het wijzigen van ingebouwde objecten. Het uitbreiden van native prototypes wordt tegenwoordig algemeen aanvaard als een slechte gewoonte, omdat het niet goed aansluit bij andere bibliotheken en code van derden. Wijzig geen objecten waarvan u niet de eigenaar bent!

Waarom behouden we niet gewoon de bestaande naam en breken we het web?

In 1996, voordat CSS wijdverspreid werd, en lang voordat ‘HTML5’ een ding werd, ging de Space Jam-website live. Tegenwoordig werkt de website nog steeds op dezelfde manier als 22 jaar geleden.

Hoe gebeurde dat? Heeft iemand die website al die jaren onderhouden en bijgewerkt telkens wanneer browserleveranciers een nieuwe functie uitbrachten?

Het blijkt dat 'maak het web niet kapot' het belangrijkste ontwerpprincipe is voor HTML, CSS, JavaScript en elke andere standaard die veel op internet wordt gebruikt. Als de introductie van een nieuwe browserfunctie ervoor zorgt dat bestaande websites niet meer werken, is dat slecht voor iedereen :

  • bezoekers van de getroffen websites krijgen plotseling een kapotte gebruikerservaring;
  • de website-eigenaren gingen van een perfect werkende website naar een niet-functionele website zonder dat ze iets veranderden;
  • browserleveranciers die de nieuwe functie leveren, verliezen marktaandeel doordat gebruikers van browser wisselen nadat ze hebben opgemerkt dat “het werkt in browser X”;
  • zodra het compatibiliteitsprobleem bekend is, weigeren andere browserleveranciers het te verzenden. De featurespecificatie komt niet overeen met de werkelijkheid ( ‘niets dan een fictiewerk’ ), wat slecht is voor het standaardisatieproces.

Zeker, achteraf gezien heeft MooTools het verkeerde gedaan, maar het breken van het internet straft hen niet, het straft gebruikers. Deze gebruikers weten niet wat een moo-tool is. Als alternatief kunnen we een andere oplossing vinden en kunnen gebruikers internet blijven gebruiken. De keuze is gemakkelijk te maken.

Betekent dit dat slechte API's nooit van het webplatform kunnen worden verwijderd?

Het hangt ervan af. In zeldzame gevallen kunnen slechte functies van internet worden verwijderd . Zelfs alleen maar uitzoeken of het mogelijk is om een ​​functie te verwijderen is een zeer lastige opgave, waarbij uitgebreide telemetrie nodig is om te kwantificeren van hoeveel webpagina's het gedrag veranderd zou zijn. Maar als de functie voldoende onveilig is, schadelijk is voor gebruikers of zeer zelden wordt gebruikt, kan dit wel worden gedaan.

<applet> , <keygen> en showModalDialog() zijn allemaal voorbeelden van slechte API's die met succes van het webplatform zijn verwijderd.

Waarom repareren we MooTools niet gewoon?

Het is een goed idee om MooTools zo te patchen dat ingebouwde objecten niet langer worden uitgebreid. Het lost het probleem echter niet op. Zelfs als MooTools een gepatchte versie zou uitbrengen, zouden alle bestaande websites die hiervan gebruikmaken een update moeten uitvoeren om het compatibiliteitsprobleem te laten verdwijnen.

Kunnen mensen hun exemplaar van MooTools niet gewoon updaten?

In een perfecte wereld zou MooTools een patch uitbrengen en zou elke website die MooTools gebruikt de volgende dag op magische wijze worden bijgewerkt. Probleem opgelost toch?!

Helaas is dit onrealistisch. Zelfs als iemand op de een of andere manier de volledige reeks getroffen websites zou identificeren, erin zou slagen contactinformatie voor elk van hen te vinden, met succes alle website-eigenaren zou bereiken en hen allemaal zou overtuigen om de update uit te voeren (wat zou kunnen betekenen dat hun volledige codebasis), zou het hele proces op zijn best jaren duren.

Houd er rekening mee dat veel van deze websites oud zijn en waarschijnlijk niet worden onderhouden. Zelfs als de beheerder er nog is, is het mogelijk dat deze geen zeer bekwame webontwikkelaar is zoals jij. We kunnen niet van iedereen verwachten dat hij zijn 8 jaar oude website gaat veranderen vanwege een webcompatibiliteitsprobleem.

Hoe werkt het TC39-proces?

TC39 is de commissie die verantwoordelijk is voor de ontwikkeling van de JavaScript-taal via de ECMAScript-standaard.

#SmooshGate zorgde ervoor dat sommigen geloofden dat “TC39 flatten wil hernoemen naar smoosh ”, maar het was een grap die extern niet goed werd gecommuniceerd. Belangrijke beslissingen, zoals het hernoemen van een voorstel, worden niet lichtvaardig opgevat, worden niet door één persoon genomen en worden zeker niet van de ene op de andere dag genomen op basis van een enkele GitHub-opmerking.

TC39 werkt volgens een duidelijk faseringsproces voor functievoorstellen. ECMAScript-voorstellen en alle belangrijke wijzigingen daarin (inclusief het hernoemen van methoden) worden besproken tijdens TC39-vergaderingen en moeten door de hele commissie worden goedgekeurd voordat ze officieel worden. In het geval van Array.prototype.flatten heeft het voorstel al verschillende stadia van overeenstemming doorlopen, helemaal tot aan fase 3, wat aangeeft dat de functie klaar is om in webbrowsers te worden geïmplementeerd. Het is gebruikelijk dat er tijdens de implementatie aanvullende specificatieproblemen optreden. In dit geval kwam de belangrijkste feedback nadat we probeerden het te verzenden: de functie, in zijn huidige staat, breekt het internet. Moeilijk te voorspellen problemen als deze zijn een deel van de reden waarom het TC39-proces niet zomaar eindigt zodra browsers een functie leveren.

TC39 werkt op basis van consensus, wat betekent dat de commissie het eens moet worden over eventuele nieuwe wijzigingen. Zelfs als smoosh een serieuze suggestie was geweest, lijkt het waarschijnlijk dat een commissielid er bezwaar tegen zou maken ten gunste van een meer gebruikelijke naam als compact of chain .

Het hernoemen van flatten naar smoosh (ook al was het geen grap) is nooit besproken tijdens een TC39-vergadering. Als zodanig is het officiële TC39-standpunt over dit onderwerp momenteel onbekend. Geen enkel individu kan namens heel TC39 spreken totdat op de volgende bijeenkomst consensus is bereikt.

TC39-bijeenkomsten worden over het algemeen bijgewoond door mensen met zeer uiteenlopende achtergronden: sommigen hebben jarenlange ervaring met het ontwerpen van programmeertalen, anderen werken met een browser of JavaScript-engine, en een toenemend aantal aanwezigen is aanwezig om de JavaScript-ontwikkelaarsgemeenschap te vertegenwoordigen.

Hoe werd SmooshGate uiteindelijk opgelost?

Tijdens de TC39-bijeenkomst van mei 2018 werd #SmooshGate officieel opgelost door flatten te hernoemen naar flat .

Array.prototype.flat en Array.prototype.flatMap geleverd in V8 v6.9 en Chrome 69.