2

ECMA-262,第 3 版[PDF]中,在第 7.6 节(“标识符”,第 26 页)下,我们看到以下注释:

美元符号仅用于机械生成的代码。

这似乎是合理的。许多通常用于生成或嵌入 JavaScript 的语言都具有特殊含义$,并且在这些语言中的 JavaScript 标识符中使用它会导致意外行为

“机械生成的条款”出现在第 2 版中。在第 1 版中,它没有出现。从第 5 版开始,它再次消失,没有任何解释,并且在第 6 版的工作草案中仍然没有出现。

如果我不得不猜测,我会假设它最初被省略了,因为没有考虑潜在的陷阱,然后在下一个版本中添加,当它很明显会引起问题时。不过,我想不出在第 5 版中再次删除它的充分理由。

是否有任何解释从规范中包含和随后删除“机械生成的条款”(来自邮件列表、新闻组或其他地方的“书面记录”)?我在任何地方都找不到这个记录。


作为一个附带问题,任何人都可以解释在第 6 版草稿中包含零宽​​度字符的理由吗?考虑到您根本看不到这些字符,这似乎会造成更多麻烦,而且我想不出任何理由您希望将这些字符包含在标识符中。


更新:最初包含“机械生成的代码”注释和包含零宽度字符在下面的 codewaggle 答案中进行了解释。唯一需要回答的是这个问题的主要焦点,即删除“机械生成的代码”注释。

4

1 回答 1

4

这是一个开始:主题:SC22 N2745 - DIS 16262 -ECMAScript 上的评论处置报告

似乎添加了“只能用于机械生成的代码”,因为那是 JAVA 的规范。

D6) 7.5:美元符号不应出现在标识符列表中,根据 TR 10176 中的建议。7.5 应参考 ISO/IEC 14652 的“i18n”规范来定义字母和数字。

>>>>>>行动:部分接受 --- ECMAScript 遵循 Java 的先例。注释将添加 $ 应仅用于机械生成的代码。<<<<<

如果你想浏览过去会议的记录,你可以看这里:
ecmascript wiki: Notes and Minutes from past meeting


关于后来
的更改:所有这些都来自邮件列表“ es5-discuss -- Discussion of ECMAScript 3.x ”。

标识符中的 ZWNJ 和 ZWJ(原为:对 4 月 ES5 最终草案标准 tc39-2009-025 的评论)

约翰考恩写道:

事实证明,Unicode 5.1 完成了繁重的工作:坏消息是,这项工作确实很繁重。当且仅当 Cf 字符在当代使用中确实具有语义区别时,您才希望允许它们。事实证明,Unicode 5.1 只允许 U+200C 和 U+200D 并且仅在某些上下文中:规则涉及了解附近标识符字符的 Script 和 Joining_Type 属性。http://unicode.org/reports/tr31/#Layout_and_Format_Control_Characters的详细信息 。

大卫-莎拉霍普伍德回答:

简单地将 U+200C 和 U+200D 添加到 IdentifierPart 而没有任何额外的上下文相关规则有什么缺点?

我认为输入法和程序员的共同责任是确保<ZWNJ><ZWJ>字符 按预期在标识符中使用;编程语言语法所需要做的就是允许它们。

请注意,“尽可能多地排除没有明显区别结果的情况”的目标(据说是出于安全原因)实际上并不适用,因为 ECMAScript 甚至不强制执行NFC 规范化。正如 UTR #31 所建议的那样,不强制执行 NFC,而是增加语法相当复杂,以防止一些潜在的(但相对无害的,AFAICS)误用<ZWNJ>and <ZWJ>,对我来说,这似乎是一组不一致的设计选择。


这个把一堆讨论拉在一起:最后呼吁就格式控制字符达成共识。问题

对此有 15 条回复,您可能需要阅读这些回复:
https ://mail.mozilla.org/pipermail/es5-discuss/2009-June/thread.html#2832

Allen Wirfs-Brock 写道:

Waldemar 在 5 月 F2F 的笔记中没有记录任何关于标识符问题<ZWNJ><ZWJ>标识符的决定。但是,我的个人笔记说我需要“保留标识符并修复语法”,这也是我对我们在会议上做出的决定的回忆。

该决策的最简单实现是简单地添加<ZWNJ><ZWJ>作为 IdentifierPart 的替代项。此外,第 7.1 节中说格式控制字符可以出现在标识符中的文字大概需要缩小为仅说<ZWNJ>and <ZWJ>

大约在 F2F 的同时,David-Sarah 提出了一个更全面的提议(重复如下),除了解决<ZWNJ><ZWJ>显着改进规则, <BOM>包括将它们从字符串文字和正则表达式中排除,并使其成为 a 的语法<BOM>错误出现在标识符中。

我不是 Unicode 专家,但我的感觉是 David-Sarah 的建议是合理的,并且可能与规范中清理 Cf 类的最初目标一致。然而,他的规则<BOM>似乎也可能使实现的词法分析阶段变得非常复杂。

我从 F2F 的感觉是,共识更倾向于我上面的简单解决方案(<ZWNJ><ZWJ>标识符中,<BOM>是空格),而不是 David-Sarah 对 <BOM>.

我需要对此做出最终决定,以便我可以相应地更新草案。根据我对 F2F 的回忆,除非有明显的共识,否则我将采用“简单解决方案”。

最后的想法?

他回复的消息,根据消息引用分成几块:

-----原始消息----- 来自:es5-discuss-bounces at mozilla.org [mailto:es5-discuss-bounces at mozilla.org] 代表 David-Sarah Hopwood 发送时间:5 月 28 日,星期四, 2009 年 5:44 PM 收件人:mozilla.org 上的 es5-discuss 主题:标识符名称的语法不允许<ZWNJ><ZWJ>

约翰考恩写道:

David-Sarah Hopwood 脚本:

省略格式控制字符<IdentifierName> 似乎只是一个疏忽。

-1

休息

确实,我忘记了我们已经讨论过这个并得出了不同的结论:

https://mail.mozilla.org/pipermail/es5-discuss/2009-April/002432.html https://mail.mozilla.org/pipermail/es5-discuss/2009-April/002435.html

休息

允许所有这些会导致与允许 BOM 相同类型的问题。即使在完全符合 Unicode 的渲染器中,它们中的大多数对周围的文本(尤其是拉丁脚本文本)也几乎没有明显的影响,更不用说使它们变得模糊的渲染器了。结果是 "foobar" 和 "foo <Cf>bar" 看起来一样但不是。

根据 Unicode 5.1,唯一真正影响标识符的自然语言含义的是 U+200C ZWNJ 和 U+200D ZWJ。这些是唯一应该在 ES5 标识符中考虑的。UAX #31(通过引用包含在 Unicode 5.1 中)指定了更窄的条件,其中 ZWNJ 和 ZWJ 是必不可少的;坚持这些条件并非易事,但可以最大限度地减少欺骗的机会。

考虑到风险,我不确定是否应该允许 ZWNJ 和 ZWJ。

休息

忘记将标识符欺骗作为安全风险的尝试最小化。如果完全允许使用 Unicode 标识符,那是不可能的。许多不同的(即使是规范化的)字符串看起来都是一样的,这是 Unicode 的一个固有特征。完全不清楚这是否是一般编程的真正安全风险——与需要对抗性代码审查的情况相反,完整的 ECMAScript 距离能够支持还有很长的路要走。

尝试最小化的有用是意外键入不同但看起来相同的标识符的机会,或者看到标识符并且无法可靠地复制它的机会。这是一个可用性问题,而不是安全问题。

对于可用性,它确实可能是允许但不允许其他格式控制字符的好<ZWNJ>方法 <ZWJ> 。我对需要这些字符来确定这一点的脚本不够熟悉,但根据 Unicode 标准中的描述,这似乎是合理的。

但是,鉴于无法防止欺骗,UAX #31 中描述的复杂的依赖于脚本的规则用于限制发生<ZWNJ>和可能发生的上下文,这似乎太过分了。<ZWJ>同样,请参阅 https://mail.mozilla.org/pipermail/es5-discuss/2009-April/002435.html

将该帖子中的提议与 , 和 的更改结合起来<NEL><ZWSP>因为<BOM>两者都影响第 7.1 节),我们最终得到了这个。

==== 对第 7.2 节的更改: - 将添加的<NEL><ZWSP>和恢复<BOM>到 WhiteSpace 和表格。

对第 7.8.4 节的更改:

DoubleStringCharacter :: SourceCharacter 但不是双引号 " 或反斜杠 \ 或 LineTerminator 或<BOM> \ EscapeSequence LineContinuation

SingleStringCharacter :: SourceCharacter 但不是单引号 ' 或反斜杠 \ 或 LineTerminator 或<BOM> \ EscapeSequence LineContinuation

NonEscapeCharacter :: SourceCharacter 但不是 EscapeCharacter 或 LineTerminator 或<BOM>

  • DoubleStringCharacter :: SourceCharacter 的 CV 但不是双引号 " 或反斜杠 \ 或 LineTerminator 或者<BOM> 是 SourceCharacter 字符本身

  • SingleStringCharacter :: SourceCharacter 的 CV 但不是单引号 ' 或反斜杠 \ 或 LineTerminator 或者<BOM> 是 SourceCharacter 字符本身。

  • NonEscapeCharacter :: SourceCharacter 但不是 EscapeCharacter 或 LineTerminator 的 CV,或者<BOM>是 SourceCharacter 字符本身。

替换第 7.1 节:

7.1 Unicode 格式控制字符

Unicode 格式控制字符(即 Unicode 字符数据库中的通用类别“Cf”中的字符,例如 LEFT-TO-RIGHT MARK 或 RIGHT-TO-LEFT MARK)是用于控制范围格式的控制代码在没有用于此的更高级别协议(例如标记语言)的情况下的文本。

<BOM>是一种格式控制字符,主要用于文本的开头,将其标记为 Unicode,并允许检测文本的编码和字节顺序。<BOM>用于此目的的字符有时也可能出现在文本的开头之后,例如作为连接文件的结果。

在 ECMAScript 源代码中,<BOM>如果字符出现在标记之前或之后,或者在连续的空白字符 (7.2) 的范围内,它们将被忽略。词法文法没有明确包括这些被忽略的<BOM>字符。字符出现在标记中是语法错误 <BOM>(也就是说,如果删除 <BOM>会导致前面和后面的字符成为同一标记的一部分)。

请注意,评论不是标记,因此上述规则允许 <BOM>字符出现在评论中。它不允许它们出现在字符串文字或正则表达式文字中(应使用转义序列 \uFEFF)。

允许源文本中的其他格式控制字符以方便编辑和显示很有用。<BOM>可以在注释、字符串文字和正则表达式文字中使用的格式控制字符除外。两个特定的格式控制字符 <ZWNJ><ZWJ>也可以用在第一个字符之后的标识符中。

  代码 单位 值 名称 正式名称

\u200C 零宽度非连接符 <ZWNJ> \u200D 零宽度连接器 <ZWJ> \uFEFF 字节顺序标记(也称为 零宽度不间断空格)<BOM>

对第 7.6 节的更改:

[...] 本标准规定了特定的字符添加:美元符号 ($) 和下划线 (_) 允许在标识符中的任何位置使用。<ZWNJ>并且<ZWJ>允许在第一个字符之后。

对第 7.8.5 节的更改:

RegularExpressionNonTerminator :: SourceCharacter 但不是 LineTerminator 或<BOM>

附件 A 的更改: - 更新上面更改的所有产品。

对附件 E 的更改: - 添加到第 7.1 节的条目:字符在标记之间和注释中被忽略,但在标记中不允许出现(包括字符串和正则表达式文字)。<ZWNJ>并且<ZWJ>在标识符中很重要,而不是被剥离。

  • 删除第 7.2 节和第 15.10.2.12 节的条目。

    (将 、 和 的添加还原<NEL><ZWSP>WhiteSpace<BOM>产生式也将其还原为 \s 字符类,而不对第 15.10.2.12 节进行任何显式更改。)

-- 大卫-莎拉霍普伍德 ⚥ http://davidsarah.livejournal.com


es5-discuss 邮件列表 es5-discuss at mozilla.org https://mail.mozilla.org/listinfo/es5-discuss


我不会尝试将所有这些放在一起并给您一个简洁的答案,也许其他人会并且您可以接受它作为答案,以此为起点。

最后一个链接:
2009 年 8 月的存档包含 ES5 的初稿和候选版本 1 讨论。

于 2013-05-09T07:44:29.277 回答