ES2015, ES2016 y más allá
El equipo de V8 da gran importancia a la evolución de JavaScript hacia un lenguaje cada vez más expresivo y bien definido que facilite la escritura de aplicaciones web rápidas, seguras y correctas. En junio de 2015, el especificación ES2015 fue ratificada por el comité de estándares TC39, convirtiéndose en la mayor actualización única del lenguaje JavaScript. Las nuevas características incluyen clases, funciones flecha, promesas, iteradores / generadores, proxies, símbolos bien conocidos y azúcar sintáctico adicional. TC39 también ha incrementado la frecuencia de nuevas especificaciones y lanzó el borrador candidato para ES2016 en febrero de 2016, para ser ratificado este verano. Aunque no tan expansiva como la actualización de ES2015 debido al ciclo de lanzamiento más corto, ES2016 introduce notablemente el operador de exponenciación y Array.prototype.includes
.
Hoy hemos alcanzado un hito importante: V8 soporta ES2015 y ES2016. Puedes usar las nuevas características del lenguaje hoy en Chrome Canary, y estarán disponibles de manera predeterminada en Chrome 52.
Dada la naturaleza de una especificación en evolución, las diferencias entre varios tipos de pruebas de conformidad, y la complejidad de mantener la compatibilidad web, puede ser difícil determinar cuándo una versión específica de ECMAScript es considerada totalmente soportada por un motor de JavaScript. Sigue leyendo para saber por qué el soporte de especificaciones es más matizado que los números de versión, por qué las llamadas a cola adecuada aún están en debate, y qué advertencias siguen vigentes.
Una especificación en evolución
Cuando TC39 decidió publicar actualizaciones más frecuentes a la especificación de JavaScript, la versión más actualizada del lenguaje se convirtió en la versión principal, aunque en borrador. Aunque las versiones de la especificación ECMAScript todavía se producen y ratifican anualmente, V8 implementa una combinación de la versión más recientemente ratificada (por ejemplo, ES2015), ciertas características que están lo suficientemente cerca de la estandarización como para ser seguras de implementar (por ejemplo, el operador de exponenciación y Array.prototype.includes()
del borrador candidato de ES2016), y una colección de correcciones de errores y enmiendas de compatibilidad web de borradores más recientes. Parte de la lógica detrás de este enfoque es que las implementaciones del lenguaje en los navegadores deben coincidir con la especificación, incluso si es la especificación la que necesita ser actualizada. De hecho, el proceso de implementar una versión ratificada de la especificación a menudo descubre muchas de las correcciones y aclaraciones que conforman la siguiente versión de la especificación.
Por ejemplo, al implementar la bandera sticky de RegExp de ES2015, el equipo de V8 descubrió que la semántica de la especificación ES2015 rompía muchos sitios existentes (incluidos todos los sitios que usan versiones 2.x.x de la popular biblioteca XRegExp). Dado que la compatibilidad es un pilar clave de la web, los ingenieros de los equipos de V8 y Safari JavaScriptCore propusieron una enmienda a la especificación RegExp para solucionar el problema, la cual fue aceptada por TC39. La enmienda no aparecerá en una versión ratificada hasta ES2017, pero sigue siendo parte del lenguaje ECMAScript y la hemos implementado para enviar la bandera sticky de RegExp.
El refinamiento continuo de la especificación del lenguaje y el hecho de que cada versión (incluido el borrador aún no ratificado) reemplaza, enmienda y aclara versiones anteriores, hace que sea complicado comprender las complejidades detrás del soporte de ES2015 y ES2016. Aunque es imposible expresarlo de manera sucinta, quizás sea más preciso decir que ¡V8 soporta el cumplimiento con el “borrador futuro continuamente mantenido del estándar ECMAScript”!
Medición de la conformidad
En un intento de dar sentido a esta complejidad de especificaciones, existen variadas formas de medir la compatibilidad del motor de JavaScript con el estándar ECMAScript. El equipo de V8, así como otros proveedores de navegadores, utilizan la suite de pruebas Test262 como el estándar de oro para la conformidad con el borrador del futuro estándar ECMAScript, el cual se mantiene continuamente. Esta suite de pruebas se actualiza constantemente para que coincida con la especificación y proporciona 16,000 pruebas funcionales discretas para todas las características y casos límite que conforman una implementación compatible y conforme de JavaScript. Actualmente, V8 pasa aproximadamente el 98% de Test262, y el 2% restante son un pequeño número de casos límite y características futuras de ES que aún no están listas para ser lanzadas.
Dado que es complicado revisar la enorme cantidad de pruebas de Test262, existen otros tests de conformidad, como la tabla de compatibilidad de Kangax. Kangax facilita la revisión para ver si una característica concreta (como las funciones flecha) ha sido implementada en un motor en particular, pero no prueba todos los casos límite de conformidad que Test262 sí verifica. Actualmente, Chrome Canary obtiene un 98% en la tabla de Kangax para ES2015 y un 100% en las secciones de Kangax correspondientes a ES2016 (por ejemplo, las secciones etiquetadas como “características de 2016” y “misceláneo de 2016” bajo la pestaña ESnext).
El 2% restante de las pruebas de la tabla Kangax para ES2015 evalúan llamadas en cola adecuadas, una característica que ha sido implementada en V8 pero que se ha desactivado deliberadamente en Chrome Canary debido a preocupaciones de experiencia del desarrollador que se detallan a continuación. Con la bandera de “Características experimentales de JavaScript” habilitada, lo que obliga a activar esta característica, Canary obtiene un 100% en la totalidad de la tabla de Kangax para ES2015.
Llamadas en cola adecuadas
Las llamadas en cola adecuadas han sido implementadas pero aún no lanzadas, dado que un cambio en la característica actualmente está bajo discusión en TC39. ES2015 especifica que las llamadas a funciones en modo estricto en posición de cola nunca deberían causar un desbordamiento de pila. Si bien esta es una garantía útil para ciertos patrones de programación, las semánticas actuales tienen dos problemas. Primero, dado que la eliminación de llamadas en cola es implícita, puede ser difícil para los programadores identificar qué funciones están realmente en posición de cola. Esto significa que los desarrolladores pueden no descubrir llamadas en cola mal ubicadas en sus programas hasta que estas desborden la pila. Segundo, implementar llamadas en cola adecuadas requiere omitir los marcos de pila de llamadas en cola de la pila, lo que pierde información sobre el flujo de ejecución. Esto tiene dos consecuencias:
- Hace más difícil entender durante la depuración cómo se llegó a un cierto punto ya que la pila contiene discontinuidades, y
error.stack
contiene menos información sobre el flujo de ejecución, lo que podría romper software de telemetría que recopila y analiza errores en el lado del cliente.
Implementar una pila sombra puede mejorar la legibilidad de las pilas de llamadas, pero los equipos de V8 y DevTools creen que la depuración es más fácil, confiable y precisa cuando la pila mostrada durante la depuración es completamente determinista y siempre coincide con el estado verdadero de la pila de la máquina virtual real. Además, una pila sombra es demasiado costosa en términos de rendimiento como para estar activada todo el tiempo.
Por estas razones, el equipo de V8 apoya firmemente designar las llamadas en cola adecuadas mediante una sintaxis especial. Hay una propuesta pendiente de TC39 llamada llamadas sintácticas en cola para especificar este comportamiento, co-patrocinada por miembros del comité de Mozilla y Microsoft. Hemos implementado y escalado llamadas en cola adecuadas tal como se especifica en ES2015 y comenzamos a implementar llamadas sintácticas en cola tal como se especifica en la nueva propuesta. El equipo de V8 planea resolver el problema en la próxima reunión de TC39 antes de lanzar llamadas en cola adecuadas implícitas o llamadas sintácticas en cola por defecto. Mientras tanto, puede probar cada versión utilizando las banderas de V8 --harmony-tailcalls
y --harmony-explicit-tailcalls
. Actualización: Estas banderas han sido eliminadas.
Módulos
Una de las promesas más emocionantes de ES2015 es el soporte para módulos de JavaScript para organizar y separar diferentes partes de una aplicación en espacios de nombres. ES2015 especifica declaraciones import
y export
para módulos, pero no cómo se cargan los módulos en un programa JavaScript. En el navegador, el comportamiento de carga fue especificado recientemente mediante <script type="module">
. Aunque se necesita trabajo adicional de estandarización para especificar APIs avanzadas de carga dinámica de módulos, el soporte de Chromium para etiquetas de scripts de módulos ya está en desarrollo. Puede seguir el trabajo de implementación en el bug de lanzamiento y leer más sobre ideas experimentales de API de carga en el repositorio whatwg/loader.
ESnext y más allá
En el futuro, los desarrolladores pueden esperar que las actualizaciones de ECMAScript sean más pequeñas, más frecuentes y con ciclos de implementación más cortos. El equipo de V8 ya está trabajando para traer características próximas como las palabras clave async
/await
, Object.values
/ Object.entries
, String.prototype.{padStart,padEnd}
y RegExp lookbehind al entorno de ejecución. Vuelve para más actualizaciones sobre nuestro progreso en la implementación de ESnext y las optimizaciones de rendimiento para las características existentes de ES2015 y ES2016+.
Nos esforzamos por continuar evolucionando JavaScript y encontrar el equilibrio adecuado entre implementar nuevas características temprano, garantizar la compatibilidad y estabilidad de la web existente y proporcionar comentarios de implementación a TC39 sobre preocupaciones de diseño. Estamos emocionados de ver las experiencias increíbles que los desarrolladores construirán con estas nuevas características.