11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: any Unicode code point

ECMAScript source text 是一系列 Unicode 码点。从 U+0000 到 U+10FFFF 的所有 Unicode 码点值,包括代理码点,都可以在 ECMAScript 语法允许的位置出现在 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本编码如何,符合规范的 ECMAScript 实现都会像处理等价的 SourceCharacter 值序列一样处理源文本,其中每个 SourceCharacter 都是一个 Unicode 码点。符合规范的 ECMAScript 实现不要求对源文本执行任何规范化,也不要求表现得仿佛正在执行源文本规范化。

组合字符序列的组成部分会被当作单独的 Unicode 码点处理,即使用户可能认为整个序列是单个字符。

Note

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也可以使用显式表示码点数值的 Unicode 转义序列表达。在注释内,这种转义序列实际上会作为注释的一部分被忽略。

ECMAScript 在 Unicode 转义序列的行为上不同于 Java 编程语言。例如,在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释内,它会被解释为行终止符(Unicode 码点 U+000A 是 LINE FEED (LF)),因此下一个码点不是注释的一部分。类似地,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量内,它同样会被解释为行终止符,而这是字符串字面量中不允许的——必须写成 \n 而不是 \u000A,才能使 LINE FEED (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释内的 Unicode 转义序列永远不会被解释,因此不能促成注释的终止。类似地,出现在 ECMAScript 程序的字符串字面量内的 Unicode 转义序列始终会构成该字面量的一部分,且永远不会被解释为行终止符或可能终止该字符串字面量的码点。

11.1.1 Static Semantics: UTF16EncodeCodePoint ( codePoint )

The abstract operation UTF16EncodeCodePoint takes argument codePoint (a Unicode code point) and returns a String. It performs the following steps when called:

  1. 断言:0 ≤ codePoint ≤ 0x10FFFF。
  2. 如果 codePoint ≤ 0xFFFF,则返回由数值为 codePoint 的代码单元组成的 String 值。
  3. cu1 为数值为 floor((codePoint - 0x10000) / 0x400) + 0xD800 的代码单元。
  4. cu2 为数值为 ((codePoint - 0x10000) modulo 0x400) + 0xDC00 的代码单元。
  5. 返回 cu1cu2字符串连接

11.1.2 Static Semantics: CodePointsToString ( text )

The abstract operation CodePointsToString takes argument text (a sequence of Unicode code points) and returns a String. 它将 text 转换为 String 值,如 6.1.4 中所述。 It performs the following steps when called:

  1. result 为空 String。
  2. text 的每个码点 codePoint,执行:
    1. result 设置为 resultUTF16EncodeCodePoint(codePoint) 的字符串连接
  3. 返回 result

11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )

The abstract operation UTF16SurrogatePairToCodePoint takes arguments lead (a code unit) and trail (a code unit) and returns a code point. 将形成 UTF-16 代理对的两个代码单元转换为一个码点。 It performs the following steps when called:

  1. 断言:lead 是前导代理,且 trail 是后尾代理。
  2. codePoint 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 codePoint

11.1.4 Static Semantics: CodePointAt ( string, position )

The abstract operation CodePointAt takes arguments string (a String) and position (a non-negative integer) and returns a Record with fields [[CodePoint]] (a code point), [[CodeUnitCount]] (a positive integer), and [[IsUnpairedSurrogate]] (a Boolean). 它将 string 解释为 UTF-16 编码码点序列,如 6.1.4 中所述,并从索引 position 处的代码单元开始读取一个码点。 It performs the following steps when called:

  1. sizestring 的长度。
  2. 断言:position ≥ 0 且 position < size
  3. firststring 内索引 position 处的代码单元。
  4. codePoint 为其数值是 first 的数值的码点。
  5. 如果 first 既不是前导代理也不是后尾代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first 是后尾代理,或 position + 1 = size,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. secondstring 内索引 position + 1 处的代码单元。
  8. 如果 second 不是后尾代理,则
    1. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. codePoint 设置为 UTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 Record { [[CodePoint]]: codePoint, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 Static Semantics: StringToCodePoints ( string )

The abstract operation StringToCodePoints takes argument string (a String) and returns a List of code points. 它返回将 string6.1.4 中所述解释为 UTF-16 编码 Unicode 文本所得的 Unicode 码点序列。 It performs the following steps when called:

  1. codePoints 为新的空 List
  2. sizestring 的长度。
  3. position 为 0。
  4. 重复,当 position < size 时,
    1. codePointCodePointAt(string, position)。
    2. codePoint.[[CodePoint]] 追加到 codePoints
    3. position 设置为 position + codePoint.[[CodeUnitCount]]
  5. 返回 codePoints

11.1.6 Static Semantics: ParseText ( sourceText, goalSymbol )

The abstract operation ParseText takes arguments sourceText (a String or a sequence of Unicode code points) and goalSymbol (a nonterminal in one of the ECMAScript grammars) and returns a Parse Node or a non-empty List of SyntaxError objects. It performs the following steps when called:

  1. 如果 sourceText 是 String,则将 sourceText 设置为 StringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为目标符号解析 sourceText,并分析解析结果以查找任何早期错误条件。解析和早期错误检测可以以实现定义的方式交错进行。
  3. 如果解析成功且未发现早期错误,则返回由解析产生的解析树根部的 Parse NodegoalSymbol 的实例)。
  4. 返回一个包含一个或多个 SyntaxError 对象的 List,这些对象表示解析错误和/或早期错误。如果存在多个解析错误或早期错误,则列表中错误对象的数量和顺序是实现定义的,但至少必须存在一个。
Note 1

考虑一段文本,它在某个特定位置有早期错误,并且在稍后位置也有语法错误。先执行解析遍历再执行早期错误遍历的实现,可能会报告语法错误而不继续进行早期错误遍历。将这两项活动交错进行的实现,可能会报告早期错误而不继续查找语法错误。第三种实现可能会报告两个错误。所有这些行为都符合规范。

Note 2

另请参见条款 17

11.2 源代码的类型

ECMAScript 代码有四种类型:

Note 1

Function code 通常作为函数定义(15.2)、箭头函数定义(15.3)、方法定义(15.4)、生成器函数定义(15.5)、异步函数定义(15.8)、异步生成器函数定义(15.6)以及异步箭头函数(15.9)的函数体提供。Function code 也从 Function 构造函数20.2.1.1)、GeneratorFunction 构造函数27.6.1.1)、AsyncFunction 构造函数27.10.1.1)以及 AsyncGeneratorFunction 构造函数27.7.1.1)的实参派生而来。

Note 2

BindingIdentifier 包含在 function code 中的实际效果是:严格模式代码的 Early Errors 会应用于一个 BindingIdentifier,该 BindingIdentifier 是函数体包含 Use Strict Directive 的函数的名称,即使周围代码不是严格模式代码。

11.2.1 指令序言和 Use Strict 指令

Directive Prologue 是出现在 FunctionBodyScriptBodyModuleBody 的初始 StatementListItemModuleItem 位置上的最长 ExpressionStatement 序列,并且该序列中的每个 ExpressionStatement 都完全由一个 StringLiteral token 后跟分号组成。分号可以显式出现,也可以由自动分号插入(12.10)插入。Directive Prologue 可以是空序列。

Use Strict DirectiveDirective Prologue 中的一个 ExpressionStatement,其 StringLiteral 恰好是码点序列 "use strict"'use strict'Use Strict Directive 不得包含 EscapeSequenceLineContinuation

Directive Prologue 可以包含多个 Use Strict Directive。不过,如果发生这种情况,实现可以发出警告。

Note

Directive PrologueExpressionStatement 会在对包含它的产生式求值期间正常求值。实现可以为不是 Use Strict Directive 且出现在 Directive Prologue 中的 ExpressionStatement 定义实现特定含义。如果存在适当的通知机制,则当实现遇到 Directive Prologue 中不是 Use Strict Directive 且没有由实现定义含义的 ExpressionStatement 时,应当发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用不受限模式或严格模式语法和语义(4.3.2)处理。在以下情形中,代码会被解释为 strict mode code

不是 strict mode code 的 ECMAScript 代码称为 non-strict code

11.2.2.1 Static Semantics: IsStrict ( parseNode )

The abstract operation IsStrict takes argument parseNode (a Parse Node) and returns a Boolean. It performs the following steps when called:

  1. 如果 parseNode 匹配的源文本strict mode code,则返回 true
  2. 返回 false

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数异质对象的求值,这些对象的求值行为以某种宿主定义的、非 ECMAScript 源文本的可执行代码形式表示。一个函数对象是在 ECMAScript 代码中定义的,还是内置函数,从调用或被这种函数对象调用的 ECMAScript 代码角度来看是不可观察的。