ES2015, ES2016 und darüber hinaus
Das V8-Team legt großen Wert auf die Weiterentwicklung von JavaScript zu einer zunehmend ausdrucksstarken und klar definierten Sprache, die es erleichtert, schnelle, sichere und korrekte Webanwendungen zu schreiben. Im Juni 2015 wurde die ES2015-Spezifikation vom TC39-Standardkomitee ratifiziert, was das größte einzelne Update der JavaScript-Sprache darstellt. Neue Funktionen umfassen Klassen, Pfeilfunktionen, Promises, Iteratoren / Generatoren, Proxy-Objekte, wohlbekannte Symbole und zusätzliche syntaktische Vereinfachungen. TC39 hat auch die Frequenz neuer Spezifikationen erhöht und im Februar 2016 den Kandidatenentwurf für ES2016 veröffentlicht, der diesen Sommer ratifiziert wird. Während es aufgrund des kürzeren Veröffentlichungszyklus nicht so umfangreich ist wie das ES2015-Update, führt ES2016 bemerkenswerterweise den Exponentiations-Operator und Array.prototype.includes
ein.
Heute haben wir einen wichtigen Meilenstein erreicht: V8 unterstützt ES2015 und ES2016. Sie können die neuen Sprachfunktionen heute mit Chrome Canary nutzen, und sie werden standardmäßig in Chrome 52 verfügbar sein.
Angesichts der Natur einer sich entwickelnden Spezifikation, der Unterschiede zwischen verschiedenen Arten von Konformitätstests und der Komplexität der Aufrechterhaltung der Web-Kompatibilität kann es schwierig sein zu bestimmen, wann eine bestimmte Version von ECMAScript von einer JavaScript-Engine vollständig unterstützt wird. Lesen Sie weiter, warum die Unterstützung der Spezifikation nuancierter ist als bloße Versionsnummern, warum proper tail calls noch diskutiert werden und welche Vorbehalte weiterhin bestehen.
Eine sich entwickelnde Spezifikation
Als TC39 beschloss, häufigere Updates der JavaScript-Spezifikation zu veröffentlichen, wurde die aktuellste Version der Sprache zur Haupt-Entwurfsversion. Obwohl Versionen der ECMAScript-Spezifikation immer noch jährlich erstellt und ratifiziert werden, implementiert V8 eine Kombination der zuletzt ratifizierten Version (z. B. ES2015), bestimmter Funktionen, die der Standardisierung so nahe sind, dass sie sicher zu implementieren sind (z. B. der Exponentiations-Operator und Array.prototype.includes()
aus dem ES2016-Kandidatenentwurf), sowie einer Sammlung von Fehlerbehebungen und Web-Kompatibilitätsänderungen aus neueren Entwürfen. Ein Teil der Begründung für solch einen Ansatz ist, dass Sprachimplementierungen in Browsern mit der Spezifikation übereinstimmen sollten, auch wenn diese aktualisiert werden muss. Tatsächlich deckt der Prozess der Implementierung einer ratifizierten Spezifikationsversion oft viele der Korrekturen und Klarstellungen auf, die die nächste Version der Spezifikation ausmachen.
Beispielsweise stellte das V8-Team bei der Implementierung des ES2015 RegExp sticky flag fest, dass die Semantik der ES2015-Spezifikation viele bestehende Websites brach (einschließlich aller Websites, die Versionen 2.x.x der beliebten XRegExp-Bibliothek verwenden). Da Kompatibilität ein Eckpfeiler des Webs ist, haben Ingenieure des V8- und Safari JavaScriptCore-Teams eine Änderung der RegExp-Spezifikation vorgeschlagen, um den Schaden zu beheben. Die Änderung wurde von TC39 angenommen. Sie wird zwar erst in einer ratifizierten Version in ES2017 erscheinen, ist aber trotzdem ein Teil der ECMAScript-Sprache, und wir haben sie implementiert, um das RegExp-sticky-Flag auszuliefern.
Die kontinuierliche Verfeinerung der Sprachspezifikation und die Tatsache, dass jede Version (einschließlich des noch nicht ratifizierten Entwurfs) frühere Versionen ersetzt, ergänzt und klärt, machen es schwierig, die Komplexität der Unterstützung von ES2015 und ES2016 zu verstehen. Obwohl es nicht einfach auszudrücken ist, ist es vielleicht am genauesten zu sagen, dass V8 die Konformität mit dem „kontinuierlich gepflegten zukünftigen ECMAScript-Standardentwurf“ unterstützt!
Konformität messen
Um die Komplexität dieser Spezifikationen zu verstehen, gibt es verschiedene Möglichkeiten, die Kompatibilität von JavaScript-Engines mit dem ECMAScript-Standard zu messen. Das V8-Team sowie andere Browseranbieter verwenden die Test262-Test-Suite als Goldstandard für die Konformität mit dem kontinuierlich gepflegten Entwurf des zukünftigen ECMAScript-Standards. Diese Test-Suite wird kontinuierlich aktualisiert, um mit der Spezifikation übereinzustimmen, und bietet 16.000 separate Funktionstests für alle Funktionen und Randfälle, die eine kompatible, konforme Implementierung von JavaScript ausmachen. Derzeit besteht V8 ungefähr 98% von Test262, und die verbleibenden 2% sind eine Handvoll Randfälle und zukünftige ES-Funktionen, die noch nicht versandfertig sind.
Da es schwierig ist, die enorme Anzahl von Test262-Tests zu überblicken, gibt es andere Konformitätstests wie die Kangax-Kompatibilitätstabelle. Kangax macht es einfach, zu prüfen, ob eine bestimmte Funktion (wie Arrow Functions) in einer bestimmten Engine implementiert wurde, testet jedoch nicht alle Konformitäts-Randfälle, die von Test262 berücksichtigt werden. Derzeit erzielt Chrome Canary einen Wert von 98% in der Kangax-Tabelle für ES2015 und 100% in den Abschnitten von Kangax, die ES2016 entsprechen (z. B. die Abschnitte mit der Bezeichnung „2016 features“ und „2016 misc“ unter dem ESnext-Tab).
Die verbleibenden 2% der Tests in der Kangax-Tabelle für ES2015 betreffen korrekte Tail-Calls, eine Funktion, die in V8 implementiert wurde, aber absichtlich in Chrome Canary deaktiviert ist aufgrund von noch offenen Bedenken zur Entwicklererfahrung, die unten ausführlich erläutert werden. Mit aktivierter „Experimentelle JavaScript-Funktionen“-Flagge, die diese Funktion erzwingt, erzielt Canary 100% in der gesamten Kangax-Tabelle für ES2015.
Korrekte Tail-Calls
Korrekte Tail-Calls wurden implementiert, aber noch nicht versandt, da eine Änderung an der Funktion derzeit bei TC39 diskutiert wird. ES2015 legt fest, dass strikte Funktionsaufrufe in Tail-Position niemals einen Stapelüberlauf verursachen sollten. Obwohl dies eine nützliche Garantie für bestimmte Programmiermuster ist, haben die aktuellen Semantiken zwei Probleme. Erstens: Da die Tail-Call-Eliminierung implizit erfolgt, kann es schwierig für Programmierer sein, zu erkennen, welche Funktionen tatsächlich in Tail-Call-Position sind. Dies bedeutet, dass Entwickler möglicherweise fehlplatzierte versuchte Tail-Calls in ihren Programmen erst entdecken, wenn sie den Stapel überlaufen. Zweitens: Die Implementierung von korrekten Tail-Calls erfordert das Auslassen der Tail-Call-Stack-Frames aus dem Stapel, was Informationen über den Ausführungsfluss verliert. Dies hat wiederum zwei Konsequenzen:
- Es wird schwieriger, während des Debuggens zu verstehen, wie die Ausführung an einen bestimmten Punkt gelangt ist, da der Stapel Unterbrechungen enthält, und
error.stack
enthält weniger Informationen über den Ausführungsfluss, was Telemetrie-Software beeinträchtigen kann, die clientseitige Fehler sammelt und analysiert.
Die Implementierung eines Shadow Stacks kann die Lesbarkeit von Call-Stacks verbessern, aber das V8- und DevTools-Team glauben, dass das Debuggen am einfachsten, verlässlichsten und genauesten ist, wenn der Stapel, der während des Debuggings angezeigt wird, vollständig deterministisch ist und immer dem tatsächlichen Zustand des echten virtuellen Maschinen-Stapels entspricht. Darüber hinaus ist ein Shadow-Stack aus Leistungssicht zu teuer, um ihn ständig eingeschaltet zu lassen.
Aus diesen Gründen unterstützt das V8-Team stark, korrekte Tail-Calls durch spezielle Syntax zu kennzeichnen. Es gibt einen ausstehenden TC39-Vorschlag namens „Syntaktische Tail-Calls“, um dieses Verhalten zu spezifizieren, wobei Ausschussmitglieder von Mozilla und Microsoft diesen Vorschlag mittragen. Wir haben korrekte Tail-Calls wie in ES2015 spezifiziert implementiert und staged und begonnen, syntaktische Tail-Calls wie im neuen Vorschlag spezifiziert zu implementieren. Das V8-Team plant, das Problem auf der nächsten TC39-Sitzung zu lösen, bevor implizite korrekte Tail-Calls oder syntaktische Tail-Calls standardmäßig versandt werden. Sie können jede Version in der Zwischenzeit mit den V8-Flags --harmony-tailcalls
und --harmony-explicit-tailcalls
testen. Update: Diese Flags wurden entfernt.
Module
Eine der aufregendsten Versprechen von ES2015 ist die Unterstützung für JavaScript-Module, um verschiedene Teile einer Anwendung in Namespaces zu organisieren und zu trennen. ES2015 spezifiziert import
und export
-Deklarationen für Module, jedoch nicht, wie Module in einem JavaScript-Programm geladen werden. Im Browser wurde das Ladeverhalten vor kurzem durch <script type="module">
spezifiziert. Obwohl zusätzliche Standardisierungsarbeiten erforderlich sind, um fortgeschrittene dynamische Modul-Lade-APIs zu spezifizieren, ist die Chromium-Unterstützung für Modul-Skript-Tags bereits in Entwicklung. Sie können die Implementierungsarbeit über den Launch-Bug verfolgen und mehr über experimentelle Loader-API-Ideen im whatwg/loader-Repository lesen.
ESnext und darüber hinaus
In Zukunft können Entwickler damit rechnen, dass ECMAScript-Updates in kleineren, häufigeren Aktualisierungen mit kürzeren Implementierungszyklen erscheinen. Das V8-Team arbeitet bereits daran, kommende Funktionen wie Schlüsselwörter async
/await
, Object.values
/ Object.entries
, String.prototype.{padStart,padEnd}
und RegExp-Lookbehind zur Laufzeit zu bringen. Besuchen Sie uns regelmäßig, um weitere Updates zu unserem ESnext-Implementierungsfortschritt und Leistungsoptimierungen für bestehende ES2015- und ES2016+-Funktionen zu erhalten.
Wir setzen uns dafür ein, JavaScript ständig weiterzuentwickeln und dabei die richtige Balance zwischen der frühzeitigen Implementierung neuer Funktionen, der Gewährleistung der Kompatibilität und Stabilität des bestehenden Webs und dem Bereitstellen von TC39-Implementierungsfeedback zu Fragen des Designs zu finden. Wir freuen uns darauf, die unglaublichen Erfahrungen zu sehen, die Entwickler mit diesen neuen Funktionen schaffen.