开发 ES3.1/ES5

在 2007 年的大多数时间里,新版 ES4 工作组都认为对 ES3.1 的投入不过是企图阻挠新版 ES4 的竞争,其中并没有实质性的技术。但是,Douglas Crockford、Pratap Lakshman 和 Allen Wirfs-Brock 仍然致力于对 ES3 规范进行增量修改,从而保证规范与时俱进,并修复各种导致互操作性问题的隐患。在发布 ES3.1 的初始目标和设计原则,并提出语言特性级的改动 [Lakshman et al. 2007] 后,他们走出了工作的第一步,即全面了解当时 Web 浏览器中 JavaScript 的现状,以及真实的 Web 与 ES3 规范之间有何不同之处。

ES3.1 工作组有一个直接的关注点,那就是微软为 Internet Explorer 实现的 JScript 以不符合 Web 标准而闻名。为了验证这些 ECMAScript 相关问题的有效性与影响范围,Allen Wirfs-Brock 请 Pratap Lakshman 进行分析,以确定 IE 的 JScript 与 ES3 规范之间一共有哪些出入。这次分析于 2007 年 9 月完成,其成果是一份长达 87 页的报告,名为《JScript 到 ES3 的偏差》[Lakshman 2007c]。这份报告分为三个主要部分。在第一部分里,报告逐个确定了「当时的 JScript 实现」与「ES3 规范的明确要求」之间存在偏差的具体位置。对每个偏差,报告都提供了 ES3 中相应被违反之处的描述、用于观察偏差的测试用例,以及在当时最新版的 IE、Mozilla Firefox、Opera 和苹果 Safari 上执行测试的结果。这些浏览器是当时公认的「前四大」浏览器。如图 29 中的示例,就展示了一个被确定出的此类偏差。其中有些偏差为 IE 所特有,有些偏差在所有受测浏览器中均存在,还有些偏差在 IE 和其他若干浏览器中存在。

  1. 2.15 String.prototype.split: §15.4.4.14
  2. ES3 陈述为「如果分隔符是一个包含捕获小括号的正则表达式,那么每次匹配分隔符时,捕获小括号的结果(包括任何未定义的结果在内)都会被拼接到输出数组中。」
  3. JScript 忽略了捕获小括号。FF 输出了空字符串而不是 undefined
  4. 示例
  5. <script>
  6. alert("A<B>bold</B>and<CODE>coded</CODE>".split(/<(\/)?([^<>]+)>/));
  7. </script>
  8. 输出
  9. IE: A,bold,and,coded
  10. FF: A,,B,bold,/,B,and,,CODE,coded,/,CODE,
  11. Opera: FF 相同
  12. Safari: FF 相同

图 29. 一个记录在 JScript 偏差报告中的 ES3 偏差 [Lakshman 2007c]。

偏差报告的第二个主要部分,确定了所有在 ES3 规范中被明确定义为「行为依赖于实现」或定义不够充分之处。这部分也提供了测试用例,以及在四个主流浏览器上执行测试的结果。报告的最后一部分则描述了 IE 中实现的各类属于 ES3 规范扩展的特性。Wirfs-Brock [2007b] 还准备了一份列表,记录了 Firefox 中实现的 ES3 扩展。在 2007 年 8 月 16 日的会议上,Douglas Crockford 和 Allen Wirfs-Brock 讨论了这些文档的草案,相应产物是一系列 ES3.1 规范中的试验性变更 [Wirfs-Brock and Crockford 2007]。

ES3.1 的开发在 2008 年 1 月的 TC39 会议上正式启动。这次会议上探讨了规范的目标,其中另有几位 TC39 成员对参与开发工作也表示出了兴趣。2 月 11 日,Lakshman 向 TC39 的内部邮件列表发送了一条消息,呼吁对 ES3.1 行动的参与。这封邮件提醒人们注意去年夏天准备的偏差与互操作性文档,并请求对这些文档提供更多反馈。在 2 月 21 日举行的电话会议上,每周两次电话会议的工作时间表得以确定。与以前的 ES3.1 讨论相比,参与这些电话会议的人数明显更多。图 30 中列出了相应的经常性参与者。起初,人们通过直发邮件来交换和讨论提案,也有一些讨论在 es4-discuss 邮件论坛进行。然而,由于与新版 ES4 主题相关的流量很大,因此很难挑选出其中与 ES3.1 相关的主题。为此在 4 月,一个单独的 es3.1-discuss80 邮件论坛 [TC39 et al. 2008] 得以成立。之后大多数在会议前后对 ES3.1 设计的讨论,都移到了这个论坛来进行。

Douglas CrockfordYahoo!
Pratap LakshmanMicrosoft
Mark S. MillerGoogle
Adam PellerIBM
Sam RubyIBM
Allen Wirfs-BrockMicrosoft
Kris ZypThe Dojo Foundation

图 30. 2008 年 ES3.1 WG 会议的经常性参与者。

在最早的讨论主题 [TC39 2008d] 里,其中有一个主题是评估 ES3.1 的总体目标,以及在解决问题和添加新特性时所应遵循的设计准则。对此,微软 Live 团队开发者和其他一些 Web 框架开发者所主张的早期立场,是避免使用任何可能导致脚本「无法在现有或旧版浏览器上解析」的新语法扩展。但这种「不允许新语法」的规则带来了过多的限制,忽视了多种浏览器已经具备某些语法扩展的事实。这个讨论的成果,是基于四种最知名的浏览器(IE、Firefox、Opera 和 Safari)而得出的「四人三票」(3 out of 4)规则,这些浏览器在微软的 JScript 偏差文档中都已经被分析过了。当四种浏览器中有三种在某特性上达成了一致或具备共通行为时,ES3.1 规范就应该以此为准。这条规则引发了关于「ES3.1 应如何处理浏览器互操作性问题」的广泛讨论。

人们一致认为,ES3.1 的首要原则是「不要破坏 Web」,亦即确定出有哪些语言变更会改变现有「已与主流浏览器相兼容的」网页的行为。但是现存的网页已有数以亿计,它们实际上依赖了 ECMAScript 规范中的哪些部分呢?对规范的哪些改动会破坏 Web 呢?有一则来自浏览器实现者的趣闻,认为由于现有网页的庞大基数,任何兼容的浏览器特性(不论用法多晦涩或令人难以置信)都可能被某些现存的页面使用。基于这种观点,在所有四种主流浏览器中共通的特性不应被更改,而四种浏览器中有三种支持的特性则很有望被标准化。但对于那些四种浏览器中只有两种支持,或在所有浏览器中都不同的特性和行为,又该怎么办呢?显然,这类特性和行为对于现有的可交互 Web 并非必需,并且还可能会在标准化过程中被进一步修改。

工作组还发现,基本上所有 ECMAScript 规范中允许实现存在的可变性,都不利于创建可兼容的网页。传统的语言规范中可能会允许「特定于实现」的差异,以便为语言实现者提供灵活性,或者适应在不同实现中已知的差异。但这种场景和万维网「通过多种独立创建的 Web 浏览器,访问全球互通的 Web」的理念,在根本上就是不匹配的。ECMAScript 规范需要比传统语言规范更规范化、更详细,并且还需要尽可能消除现有实现上的差异。经过 2 月的初步讨论,Douglas Crockford [2008a] 在 TC39 Wiki 上发布了修订后的 ES3.1 目标(图 31)。

  1. 1. 对浏览器实现的统一:考虑采纳 4 种浏览器品牌中已有 3 种实现的特性,或 4 种用户计算机中已有 3 种部署的特性,减少跨浏览器的不兼容性。
  2. 2. ES3.1 应通过减少易混淆或麻烦的结构来改进语言,使业余开发者受益。
  3. 3. ES3.1 应通过减少易混淆或麻烦的结构来改进语言,使主要网站受益。
  4. 4. ES4 应成为 ES3.1 的超集。
  5. 5. ES3.1 应为语言的安全子集提供良好基础。
  6. 6. ES3.1 应尝试纠正 ES3 中的错误。
  7. 7. ES3.1 新特性应需要具体演示。
  8. 8. ES3.1 可能会废弃(或选择性删除)影响性能、安全性和可靠性的特性。
  9. 9. ES3.1 应提供可虚拟化性,允许对宿主对象的模拟。

图 31. 2008 年 2 月 ES3.1 修订后的目标 [Crockford 2008a]。

在 2008 年 3 月的面对面会议上,工作组一致认为应该立即开始编写实际的 ES3.1 规范文档。Pratap Lakshman 在会议上提供了一份经过纠正的 ES3 规范,其改动来源于 Mozilla 维护的勘误表 [Horwat 2003b]。工作组同意将其用作 ES3.1 基础文档,并请 Lakshman 担任编辑。跟以前的版本一样,规范文档将使用微软 Word 编写。通过相对于第三版的修订追踪(change tracking)功能,可以跟踪规范的演变情况,从而进行评审,并确保这些改动能被重新集成到新版 ES4 中。工作组成员被分配到了对具体新特性的规范文本开发上(图 32)。工作完成后,Lakshman 会将它们合并到 master 草案中。

Lakshman基于 Mozilla「数组扩展」的新数组方法,以及 reducereduceRight
Lakshman为字符串添加数组式的下标索引支持
LakshmanDate 的改进
Lakshman严格模式下的属性访问语义
CrockfordJSON 支持
CrockfordUnicode 更新
Peller推荐基于微软偏差文档的改动
Ruby十进制小数
Zyp对象字面量的 getter 和 setter
Wirfs-Brock用于创建和检视属性的静态方法
Wirfs-Brock更新伪代码记号和约定
Miller对象的 freeze 和 seal,并对整份规范从安全角度进行评审

图 32. 截至 2008 年 3 月 28 日的 ES3.1 工作组任务分配 [TC39 2008c]。

2008 年 5 月 29 日,Pratap Lakshman 在 TC39 Wiki 上发布了 ES3.1 规范的初稿。更新后的草案通常每周发布一次,而「评审草案」则在每次 TC39 会议之前两到三周发布。在 2008 年 5 月 29 日到 2009 年 3 月 2 日之间,共有 26 个中间草案发布。

长期以来,IBM 一直主张 JavaScript 需要支持十进制小数运算。从 1998 年 11 月 19 日的 TC39 工作组会议起,Mike Cowlishaw 就希望将这一特性包含在 ES3 和初版 ES4 中。当 IBM 重新参与 TC39,开始贡献新版 ES4 和 ES3.1 时,他们再次强烈建议引入对十进制小数的支持。来自 IBM 的成员向 TC39 明确了一点,即 IBM 的政策是「反对所有不支持十进制小数运算的新语言标准」。TC39 中的许多人都对这一目标的可行性表示怀疑,但是 Brendan Eich 支持 IBM,他指出 Firefox 最常报告的的错误来自于那些不了解二进制浮点运算语义的 JavaScript 开发者。Eich 帮助了 Sam Ruby 开始开发原型。他们使用 Mozilla 的 SpiderMonkey 引擎,将 IEEE 754-2008 浮点十进制小数实现为了新的原始数据类型,使其可以在混合模式(mixed-mode)表达式中与 Number 类型结合使用。在 2008 年 9 月和 2008 年 11 月的 ES3.1 草案中,已经纳入了相当完整的十进制小数特性规范。但在 2008 年 11 月 19 日至 20 日的 TC39 会议上,需要就 ES3.1 草案中所应保留或删除的新特性做出最终决定。会议的第一项议题便是十进制小数运算支持。委员会的结论是,十进制小数设计仍然太不成熟,并存在剩余的设计问题,这些问题在不延迟 ES3.1 的情况下是不太可能解决的。会议纪要 [TC39 2008a] 中记录了这些担忧,并总结如下:

由于存在这些问题,因此决定将对十进制小数的支持推迟到 ECMAScript 的 Harmony 修订版。与会者承认,当前在 ECMAScript 十进制小数提案的开发上已经有非常显著的进展,并要感谢 IBM 的 Sam Ruby 对开发所投入的努力。与会者鼓励 Sam 和其他 TC39 成员继续开发该提案,并对「完全集成且通用的」十进制小数运算提案版本成为 Harmony 修订版的组成部分感到乐观。

在 2009 年 1 月发布的下一个评审草案中,没有关于十进制小数运算的资料。

由于微软将 JavaScript 的开发职责转移给了位于 Redmond 的新小组,并且 Pratap Lakshman 拒绝了调迁的机会,因此他在 2009 年 3 月 25 日至 26 日的会议 [TC39 2009d] 上宣布辞去 ECMA-262 编辑的职务。委员会任命 Allen Wirfs-Brock 接任他的编辑职位。

Wirfs-Brock 回忆说,在 TC39 会议期间的某个休息时间,他找到了 Brendan Eich,建议将 ES3.1 重命名为整数级的版本。关于新名称的说法是,ES3.1 已经成长为 ECMA-262 的全面修订,与之前的三个版本一样重要。而新版 ES4 虽然已经终止,但其相关作品已经广为宣传。因此如果将 ES3.1 指定为第 4 版,会对 JavaScript 开发者社区和 Web 搜索引擎造成混乱。作为替代,Wirfs-Brock 建议 Ecma 永久停用 ECMA-262 第 4 版,并发布 ES3.1 作为第 5 版。对此 Eich 表示同意。在会议恢复后,他们向委员会提出了这个想法,并获得了接受。在认可了对版本号的更新后,会上委员会还同意接受以当时最新的草案作为最终草案。2009 年 4 月 7 日,「最终草案」以第 5 版的名义发布 [Lakshman et al. 2009]。该草案发布后,还有五份发行候选(release-candidate)草案发布,其中包含了一些较小的技术和编辑更改。在 2009 年 8 月苹果发现 [Hunt 2009],使 arguments 对象继承自 Array.prototype 的决定,会与 Prototype 框架产生意外的交互,从而破坏多个苹果网站和 NASA 网站。于是这一改动从最终规范中删除。

2009 年 9 月 23 日,TC39 [2009b] 投票确认了 ES5 的完成,并将其提交给 Ecma GA 大会供批准。Ecma GA 大会审核批准的最终草案于 2009 年 10 月 28 日发布。在第 3 版获得批准十年后,《ECMA-262 第 5 版》于 2009 年 12 月 3 日由 GA 大会批准 [Ecma International 2009a]。GA 大会投票收到 19 票赞成和 2 票反对。IBM 之所以投反对票,是因为标准未包含对十进制小数运算的支持。Intel 则表示他们投反对票,只是因为他们缺乏足够的时间对规范进行完整的知识产权审查。

《ECMA-262 第 5 版》是 ISO/IEC ECMAScript 标准的快速通道修订版,它经历了 ISO 国家机构的审核过程。Allen Wirfs-Brock 根据审核过程中的反馈,将许多编辑上的修订纳入了规范。这份修订版于 2011 年 6 月作为《ECMA-262 第 5.1 版》和《ISO/IEC 16262 第 3 版》发布。