FAQ zu SmooshGate

Was für ein Fließ ist passiert?!

Ein Vorschlag für die JavaScript-Sprachfunktion Array.prototype.flatten erweist sich als nicht webkompatibel. Durch die Einführung der Funktion in Firefox Nightly funktionierte mindestens eine beliebte Website nicht mehr. Da der problematische Code Teil der weitverbreiteten MooTools-Bibliothek ist, sind wahrscheinlich viele weitere Websites betroffen. MooTools wird 2018 zwar nicht häufig für neue Websites verwendet, war aber früher sehr beliebt und ist immer noch auf vielen Produktionswebsites vorhanden.

Der Angebotsverfasser hat scherzhaft vorgeschlagen, flatten in smoosh umzubenennen, um das Kompatibilitätsproblem zu vermeiden. Der Witz war nicht klar für alle klar, manche glaubten, dass der neue Name bereits entschieden war, und die Dinge eskalierten schnell.

Was macht Array.prototype.flatten?

Array.prototype.flat, ursprünglich als Array.prototype.flatten vorgeschlagen, vereinfacht Arrays rekursiv bis zum angegebenen depth, der standardmäßig 1 ist.

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

Derselbe Vorschlag enthält Array.prototype.flatMap, was dem Array.prototype.map entspricht, mit der Ausnahme, dass das Ergebnis in einem neuen Array zusammengefasst wird.

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

Was verursacht MooTools?

MooTools definiert eine eigene nicht standardmäßige Version von Array.prototype.flatten:

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

Die flatten-Implementierung von MooTools unterscheidet sich vom vorgeschlagenen Standard. Das ist jedoch nicht das Problem. Wenn Browser Array.prototype.flatten nativ ausliefern, überschreibt MooTools die native Implementierung. Dadurch wird sichergestellt, dass Code, der auf dem MooTools-Verhalten basiert, wie vorgesehen funktioniert, unabhängig davon, ob native flatten verfügbar ist. So weit, so gut!

Leider passiert dann etwas anderes. MooTools kopiert alle seine benutzerdefinierten Array-Methoden nach Elements.prototype (wobei Elements eine MuoTools-spezifische API ist):

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

for-in iteriert über „aufzählbare“ Attribute, die keine nativen Methoden wie Array.prototype.sort umfasst, aber regelmäßig zugewiesene Attribute wie Array.prototype.foo = whatever. Wenn Sie jedoch ein nicht aufzählbares Attribut wie Array.prototype.sort = whatever überschreiben, bleibt es nicht aufzählbar.

Derzeit erstellt Array.prototype.flatten = mooToolsFlattenImplementation eine aufzählbare flatten-Eigenschaft, die später nach Elements kopiert wird. Wenn Browser jedoch eine native Version von flatten ausliefern, wird diese nicht aufzählbar und nicht nach Elements kopiert. Jeder Code, der auf dem Elements.prototype.flatten von MooTools basiert, ist jetzt nicht mehr verfügbar.

Obwohl es so aussieht, als würde das Problem durch Ändern der nativen Array.prototype.flatten in eine Auflistung behoben werden, würde es wahrscheinlich noch mehr Kompatibilitätsprobleme verursachen. Jede Website, die for-in zur Iteration über ein Array verwendet (was zwar nicht sinnvoll ist, aber es passiert), würde plötzlich eine zusätzliche Schleifenwiederholung für das Attribut flatten erhalten.

Ein größeres Problem liegt hier in der Änderung integrierter Objekte. Das Erweitern nativer Prototypen wird derzeit im Allgemeinen als schlechte Praxis anerkannt, da es sich nicht gut mit anderen Bibliotheken und Drittanbietercode zusammensetzen lässt. Ändern Sie keine Objekte, die Ihnen nicht gehören.

Warum behalten wir nicht einfach den bestehenden Namen und machen so das Web kaputt?

1996, bevor sich CSS verbreitete, und lange bevor "HTML5" auf dem Markt wurde, ging die Space Jam-Website online. Heute funktioniert die Website noch wie vor 22 Jahren.

Wie ist das passiert? Hat jemand die Website über die Jahre gepflegt und jedes Mal aktualisiert, wenn Browser-Anbieter eine neue Funktion eingeführt haben?

„Mach das Web nicht zerstören“ ist das wichtigste Designprinzip für HTML, CSS, JavaScript und alle anderen weit im Web weit verbreiteten Standards. Wenn die Einführung einer neuen Browserfunktion dazu führt, dass vorhandene Websites nicht mehr funktionieren, ist das für alle schlecht:

  • Die Nutzererfahrung auf den betroffenen Websites kann plötzlich beeinträchtigt werden.
  • dass die Websiteinhaber:innen von einer perfekt funktionierenden Website zu einer nicht funktionsfähigen Website wechselten, ohne dass sie etwas ändern mussten.
  • Browseranbieter, die die neue Funktion anbieten, verlieren Marktanteile, da Nutzer den Browser wechseln, nachdem sie bemerkt haben, dass sie mit Browser X funktionieren.
  • Sobald das Kompatibilitätsproblem bekannt ist, verweigern andere Browser-Anbieter den Versand des Pakets. Die Funktionsspezifikation entspricht nicht der Realität ("nothing but a work of Fiction"), was für den Standardisierungsprozess schlecht ist.

Natürlich hat MooTools im Nachhinein das Falsche getan, aber durch den Angriff im Web werden Nutzer nicht bestraft, sondern bestraft. Diese Nutzer wissen nicht, was ein MOO-Tool ist. Stattdessen können wir nach einer anderen Lösung suchen und die Nutzer können weiterhin das Web verwenden. Die Entscheidung ist leicht zu treffen.

Bedeutet das, dass fehlerhafte APIs niemals von der Webplattform entfernt werden können?

Das ist unterschiedlich. In seltenen Fällen können fehlerhafte Funktionen aus dem Web entfernt werden. Selbst herauszufinden, ob es möglich ist, eine Funktion zu entfernen, ist sehr schwierig. Sie erfordert umfangreiche Telemetrie, um zu quantifizieren, wie viele Webseiten ihr Verhalten geändert hätten. Wenn die Funktion jedoch ausreichend unsicher ist, Nutzern schaden oder sehr selten verwendet wird, ist dies möglich.

<applet>, <keygen> und showModalDialog() sind Beispiele für fehlerhafte APIs, die erfolgreich von der Webplattform entfernt wurden.

Warum reparieren wir nicht einfach MooTools?

Es empfiehlt sich, MooTools so zu patchen, dass integrierte Objekte nicht mehr erweitert werden. Das vorliegende Problem wird dadurch jedoch nicht gelöst. Selbst wenn MooTools eine Patchversion veröffentlichen würde, müssten alle vorhandenen Websites, die diese verwenden, aktualisiert werden, damit das Kompatibilitätsproblem nicht mehr auftritt.

Können andere nicht einfach ihre MooTools-Kopie aktualisieren?

In einer perfekten Welt würde MooTools einen Patch veröffentlichen und jede einzelne Website, die MooTools nutzte, würde automatisch am nächsten Tag aktualisiert. Das Problem ist gelöst, oder?!

Das ist leider unrealistisch. Selbst wenn jemand alle betroffenen Websites ermitteln, Kontaktinformationen für jede einzelne Website finden und alle Websiteinhaber kontaktieren und sie davon überzeugen könnte, die gesamte Codebasis zu refaktorieren, würde der gesamte Prozess im Idealfall Jahre in Anspruch nehmen.

Denken Sie daran, dass viele dieser Websites alt und wahrscheinlich nicht gepflegt werden. Auch wenn der Administrator noch da ist, kann es sein, dass er kein hochqualifizierter Webentwickler wie Sie ist. Wir können nicht erwarten, dass jeder seine acht Jahre alte Website aufgrund eines Kompatibilitätsproblems mit dem Web ändert.

Wie funktioniert der TC39-Prozess?

TC39 ist der Ausschuss, der dafür zuständig ist, die JavaScript-Sprache anhand des ECMAScript-Standards zu entwickeln.

#SmooshGate hat einige glaubten, dass „TC39 möchte flatten in smoosh umbenennen“, aber es war nur ein Scherz, der extern nicht gut kommuniziert wurde. Wichtige Entscheidungen wie die Umbenennung eines Vorschlags werden nicht leichtfertig getroffen, sie werden nicht von einer einzigen Person getroffen und definitiv nicht über Nacht auf der Grundlage eines einzelnen GitHub-Kommentars getroffen.

TC39 verwendet für Funktionsvorschläge einen klaren Staging-Prozess. ECMAScript-Vorschläge und alle größeren Änderungen daran (einschließlich Umbenennung von Methoden) werden während TC39-Meetings diskutiert und müssen vom gesamten Ausschuss genehmigt werden, bevor sie offiziell werden. Bei Array.prototype.flatten hat das Angebot bereits mehrere Phasen der Vereinbarung bis hin zu Phase 3 durchlaufen. Das bedeutet, dass die Funktion in Webbrowsern implementiert werden kann. Während der Implementierung treten häufig zusätzliche Spezifikationsprobleme auf. In diesem Fall kam das wichtigste Feedback nach dem Versuch, es zu versenden: Das Feature in seinem aktuellen Zustand beeinträchtigt das Web. Schwer vorhersehbare Probleme wie diese sind einer der Gründe, warum der TC39-Prozess nicht nur endet, wenn Browser eine Funktion ausliefern.

TC39 arbeitet auf Konsens, das heißt, der Ausschuss muss sich über alle neuen Änderungen einigen. Selbst wenn smoosh ein seriöser Vorschlag wäre, würde ein Ausschussmitglied Einspruch dagegen einlegen und stattdessen einen gebräuchlicheren Namen wie compact oder chain verwenden.

Die Umbenennung von flatten zu smoosh (auch wenn es kein Scherz war) wurde noch nie in einer TC39-Besprechung besprochen. Daher ist die offizielle Haltung von TC39 zu diesem Thema derzeit unbekannt. Eine einzelne Person kann erst dann für alle TC39 sprechen, wenn es beim nächsten Meeting eine Einigung erzielt hat.

An TC39-Meetings nehmen im Allgemeinen Menschen mit sehr unterschiedlichen Hintergründen teil. Einige haben jahrelange Erfahrung im Design von Programmiersprachen, andere arbeiten an einem Browser oder einer JavaScript-Engine und immer mehr Assistenten repräsentieren die JavaScript-Entwickler-Community.

Wie wurde SmooshGate letztendlich gelöst?

Während der TC39-Besprechung im Mai 2018 wurde #SmooshGate offiziell beschlossen, indem flatten in flat umbenannt wurde.

Array.prototype.flat und Array.prototype.flatMap werden in V8 v6.9 und Chrome 69 ausgeliefert.