Skip to content
公众号 - 佳佳的博客

JEP 292: Implement Selected ECMAScript 6 Features in Nashorn | 在 Nashorn 中实现选择的 ECMAScript 6 功能

摘要

在 Nashorn 中实现一组选定的 ECMA-262 第 6 版(也称为 ECMAScript 6 或 ES6)引入的许多 新功能

目标

在 JDK 9 中正确实现 ES6 的大量功能。

由于这是一个庞大的工作,我们需要分几个步骤来实现 ES6,其中 JDK 9 只是第一步。剩下的 ES6 功能可能会在 JDK 9 的更新版本和未来的主要 JDK 版本中实现。

动机

ECMAScript 6 于 2015 年 6 月发布。迄今为止,没有任何 JavaScript 引擎完全支持 ES6,但包括 Google V8、Mozilla Spidermonkey 和 JavaScriptCore 在内的主要引擎最近在 实现 ES6 方面取得了重大进展。

我们从 JDK 8u40 开始使用 Nashorn 实现 ES6 中的 JEP 203letconst)。为了跟上其他引擎的步伐,我们计划在 JDK 9 中添加对 ECMAScript 6 功能的重要子集的支持。

描述

ECMAScript 6 包括以下新功能:

  • 箭头函数:使用 => 语法定义函数的简洁方式

  • 类:使用继承、构造函数和方法来定义类

  • 增强的对象字面量:支持特殊和计算的属性键

  • 模板字符串:动态计算的多行字符串

  • 解构赋值:使用对象或数组语法进行赋值绑定

  • 默认参数、剩余参数和扩展参数:更灵活的参数传递方式

  • letconst 和块作用域:变量和常量的块级声明

  • 迭代器和 for..of 循环:用于迭代任意对象的协议

  • 生成器:一种创建迭代器的特殊函数

  • Unicode:完全支持 Unicode 并保持向后兼容

  • 模块:语言级别支持模块的定义

  • 模块加载器:支持动态加载、隔离和编译钩子

  • MapSetWeakMapWeakSet:各种新的集合类

  • 代理:允许创建具有特殊行为的对象

  • 符号:一种新的唯一属性键

  • 可子类化的内建对象:可对内建对象(如 ArrayDate)进行子类化

  • Promises:用于异步任务完成的 API

  • MathNumberStringObject API:内建对象上的各种新函数

  • 二进制和八进制字面量:数字字面量的新形式

  • 反射 API:用于执行元编程操作的 API

  • 尾调用:允许递归代码而不会导致无限堆栈增长

在这些功能中,我们已经在 JDK 8u40 中实现了 letconst 和块作用域,作为 JEP 203。其他一些功能已经进行了原型开发,并应该添加到 JDK 9 初始版本支持的 ES6 功能列表中。其中包括以下项目:

  • 模板字符串
  • letconst 和块作用域
  • 迭代器和 for..of 循环
  • MapSetWeakMapWeakSet
  • 符号
  • 二进制和八进制字面量

其他功能已经进行了部分原型开发,并且在有限的时间内可能完成。这些功能有望包含在 JDK 9 的更新版本中:

  • 箭头函数
  • 增强的对象字面量
  • 解构赋值
  • 默认参数、剩余参数和扩展参数
  • Unicode
  • 可子类化的内建对象
  • Promises
  • 代理
  • MathNumberStringObject API
  • 反射 API

剩下的功能更为复杂,可能需要更长时间来实现。虽然在 JDK 9 的更新版本中可能包含其中一些功能,但我们目前计划将它们作为未来主要的 JDK 版本的一部分。这些功能包括:

  • 生成器
  • 模块
  • 模块加载器
  • 尾调用

除了 ES6 功能的实现外,JDK 9 Nashorn 存储库中的 Nashorn 解析器已经支持 ES6 的语法变化。

备选方案

除了提出的迭代方法,我们可以选择暂时忽略 ECMAScript 6,而是专注于改进我们现有的基于 ECMAScript 5 的实现。

或者,我们可以尝试一次性实现 ES6。然而,这将阻止我们及早获得反馈并发现错误。此外,ES6 中的新功能数量和规模使得这种方法不切实际。

不做任何努力去实现 ES6 将是一个错误,并向用户和客户传递错误的信息。

测试

作为实现 ES6 的工作的一部分,我们开发了一个基本的功能测试集,将成为 JEP 的一部分。

我们还开始运行官方 ECMAScript 遵循性测试套件 test262 的 ES6 版本。初步结果是令人鼓舞的。然而,由于许多测试要求完整的 ES6 实现,因此将 ES5.1 版本的 test262 切换为我们的主要测试套件是不可行的。

在开发和集成本 JEP 时,我们将依赖于 ES6 版本的 test262 来发现错误并填补缺失的部分。计划在接近完全 ES6 功能时将 ES6 版本作为我们的主要 ES6 测试套件。

风险和假设

ECMAScript 6 规范已经发布,其中的大部分已在各种 JavaScript 引擎中实现,因此不再存在移动规范或规范文本的歧义风险。

我们对功能的优先级排序可能会忽略一些开发者需要的功能。然而,提出的迭代方法确保随着时间的推移交付所有缺失的功能。

依赖关系

ES6 内部各个功能之间存在依赖关系,并且我们选择按照复杂性递增的顺序来处理这些特性。