6.2 ECMAScript Specification Types
ECMAScript规范类型是用在规范的算法中,用来描述ECMAScript构造语法以及ECMAScript语言类型语法的的元数据。规范类型有: Reference, List, Completion, Property Descriptor, Lexical Environment, Environment Record, Data Block。规范类型的值是人为的,不是规范实现时必须实现的。规范类型的值是用来描述ECMAScript表达式执行结果的中间态的,不能作为存储为对象的属性或者任何一种ECMAScript变量的值
6.2.1 List和Record类型
List类型是用来说明在new表达式中的参数列表、函数调用以及其他有用到有序的一组值的算法中。List类型中值的是就是简单的单个值,这个序列可以是任何长度。这个序列的索引是从0开始的,类似数组访问那样的语法就能访问List中的值,比如arguments[2]就是arguments这个List中的第三个元素
为了便于在本规范中表示List,可以使用字面声明List,比如« 1, 2 »就是定义了一个有连个元素组成的List,空List表示为 « ».
Record类型是用来描述数据集合的。一个Record类型由一个或多个字段组成。字段值要么是ECMAScript值或者关联另一个Record的抽象值,字段名总是用双方括号包裹如[[Value]]
为了便于在规范中表示Record类型,可以用对象字面量的形式表示Record类型。比如{[[字段1]]: 42, [[字段2]]: false, [[字段3]]: empty } 就定义了一个由三个字段组成的Record。字段名的顺序是没有意义的,任何没有明确列出来的字段都认为是不存在的。
在规范的文本以及算法中,点符号可能会用来引用Record的字段值,比如如果R是之前声明的Record,那么R.[[字段2]]就是"R的名为[[字段]]的字段"的简写
一些常用的Record的字段名可能以及命名了,并且会有一个前缀来识别这个Record是一个特别的描述性Record,比如PropertyDescriptor{[[Value]]: 42, [[Writable]]: false, [[Configurable]]: true}
6.2.2 Completion Record类型
Completion类型是一个Record用来解释运行时的传值以及控制流比如(break,continue,return,throw)等语句。 Completion类型的值就是Record指,字段如表8中所列。
字段 | 值 | 意义 |
---|---|---|
[[Type]] | normal, break, continue, return, throw 其中一个 | 发生的 completion 的类型 |
[[Value]] | 任意的 ECMAScript 语言类型值或者空 | 产生的值. |
[[Target]] | 任意 ECMAScript 字符串或者空 | 控制转移的目标指示 |
"abrupt completion"指的就是任意一个其[[Type]]值不是normal的completion
6.2.2.1 NormalCompletion
这个抽象操作只有一个参数,如:
- 返回 NormalCompletion(argument)
是如下的简写:
- 返回 Completion{[[Type]]: normal, [[Value]]: argument, [[Target]]: empty}.
6.2.2.2 隐式 Completion 值
本规范中的算法一般都是隐式的返回一个[[Type]]为normal的 Completion Records。除非在上下文中显示的返回了一个不是Completion Record的值,比如:
- 返回 "Infinity"
这就和下面是同一个意思:
- 返回 NormalCompletion("Infinity")
然而如果"return"表达式的值就是Completion Record的字面量构造器,结果就是把Completion Record的结果返回。如果"return"表达式是调用一个抽象操作,那"return"返回这个抽象操作产生的Completion Record
Completion(completionRecord) 这个抽象操作是为了强调之前计算得到的Completion Record将被返回。Completion这个抽象操作只有一个参数completionRecord,其执行步骤如下:
- 断言: completionRecord 是 Completion Record.
- 返回 completionRecord 作为 Completion Record 这个抽象操作的结果
"return"语句没有返回任何值,和下面的是同一个意思:
- 返回 NormalCompletion(undefined).
任何对一个Completion Record值的引用都不是直接的要完整的Completion Record的值,而是对[[Value]]字段值得引用,除非Completion Record是一个abrupt completion
6.2.2.3 Throw an Exception (抛出异常)
算法中的步骤意思说要抛除异常如下所示:
- Throw a TypeError 异常
和下面的是同一个意思
- 返回 Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}.
6.2.2.4 ReturnIfAbrubt
算法中有如下步骤,或者说有等价于下面的步骤:
- ReturnIfAbrupt(argument)
意味着:
- 如果 argument 是 abrupt completion, 返回 argument.
- 否则如果 argument 是 Completion Record, 使 argument 为 argument.[[Value]].
算法中有如下步骤,或者说有等价于下面的步骤:
- ReturnIfAbrupt(AbstractOperation()).
意味着:
- 使 hygienicTemp 为 AbstractOperation().
- 如果 hygienicTemp 是 abrupt completion, 返回 hygienicTemp.
- 或者如果 hygienicTemp 是 Completion Record, 使 hygienicTemp 为 hygienicTemp.[[Value]].
hygienicTemp 是临时的,并且只在ReturnIfAbrupt相关步骤中能看见
6.2.2.5 UpdateEmpty ( completionRecord, value)
这个抽象操作步骤如下:
- 断言: 如果 completionRecord.[[Type]] 是 return 或者 throw, 那么 completionRecord.[[Value]] 不是空.
- 如果 completionRecord.[[Value]] 不是空, 返回 Completion(completionRecord).
- 返回 Completion{[[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }.
6.2.3 引用规范类型
注意:引用类型是用来解释比如:delete、typeof以及赋值操作和super关键字等其他语言功能。比如赋值表达式中的左侧操作符就是想产生一个引用
一个Reference是一个已声明的命名或者属性绑定。一个引用由三部分组成,base值,引用的name以及标识严格模式的布尔值。base值要么是undefined、Object、Boolean、String、String、Number或者环境记录项。一个base值如果是undefined,意思是说这个引用还没有绑定。引用name是String或者Symbol值
Super引用是用来标识一个命名变量是用了super关键字,Super引用有一个额外的thisValue,并且其base值永远不会是环境记录项
下面的抽象操作在本规范中是用来访问引用的组成部分的:
- GetBase(V). 返回引用V的 base值.
- GetReferencedName(V). 返回V的引用名.
- IsStrictReference(V). 返回V的严格模式标识符.
- HasPrimitiveBase(V). 如果Type(base)为 Boolean, String, Symbol, or Number,返回true.
- IsPropertyReference(V). 如果 base 值是 object 或者 HasPrimitiveBase(V) 为 true; 否则返回 false.
- IsUnresolvableReference(V). 如果base值是undefined返回true,否则返回false.
- IsSuperReference(V). 如果 reference 有thisValue部分,返回 true.
接下来的抽象操作是在引用上操作的:
6.2.3.1 GetValue(V)
- ReturnIfAbrupt(V).
- 如果 Type(V) 不是 Reference, 返回 V.
- 使 base 为 GetBase(V).
- 如果 IsUnresolvableReference(V) 为 true, 抛出 ReferenceError 异常.
- 如果 IsPropertyReference(V) 为 true, 那么
- 如果 HasPrimitiveBase(V) 为 true, 那么
- 断言: 在这种情况下,base永远不会是null或者undefined
- 使 base 为 ToObject(base).
- Return ? base.[Get], GetThisValue(V)).
- 如果 HasPrimitiveBase(V) 为 true, 那么
- 否则 base 必须是 Environment Record,
- Return ? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)) (see 8.1.1).
第5步中创建的Object可能无法在外界被访问到,以及没法使用Object的[[Get]]操作。实现时可能选择不要实际的创建这个Object
6.2.3.2 PutValue(V, W)
- ReturnIfAbrupt(V).
- ReturnIfAbrupt(W).
- 如果 Type(V) 不是 Reference, 抛出 ReferenceError 异常.
- 使 base 为 GetBase(V).
- 如果 IsUnresolvableReference(V) 为 true, 那么
- 如果 IsStrictReference(V) 如果 true, 那么
- 抛出 ReferenceError 异常.
- 使 globalObj 为 GetGlobalObject().
- 返回 Set(globalObj, GetReferencedName(V), W, false).
- 如果 IsStrictReference(V) 如果 true, 那么
- 否则如果 IsPropertyReference(V) 为 true, 那么
- 如果 HasPrimitiveBase(V) 为 true, 那么
- 断言: 在这种情况下,base永远不会是null或者undefined.
- 设置 base 为 ToObject(base).
- 使 succeeded 为 ? base.[Set], W, GetThisValue(V)).
- 如果 succeeded 是 false 并且 IsStrictReference(V) 为 true, 抛出TypeError 异常.
- 返回.
- 如果 HasPrimitiveBase(V) 为 true, 那么
- 否则 base 必须是 Environment Record,
- 返回 ? base.SetMutableBinding(GetReferencedName(V), W, IsStrictReference(V)) (见 8.1.1).
注意:第6步中创建的Object可能无法在外界被访问到,以及没法使用Object的[[Set]]操作。实现时可能选择不要实际的创建这个Object
6.2.3.3 GetThisValue(V)
- 断言:IsPropertyReference(V) 为 true.
- 如果 IsSuperReference(V) 为 true, 那么
- 返回V的 thisValue .
- 返回 GetBase(V).
6.2.3.4 InitializeReferencedBinding (V, W)
- ReturnIfAbrupt(V).
- ReturnIfAbrupt(W).
- 断言: Type(V) 是 Reference.
- 断言: IsUnresolvableReference(V) 是 false.
- 使 base 为 GetBase(V).
- 断言: base 是 Environment Record.
- 返回 base.InitializeBinding(GetReferencedName(V), W).
6.2.4 属性描述符规范类型
属性描述符类型是用来解释对象的属性的操作以及具体描述属性的。属性描述符的值类型是Record。任何一个字段名都是一个特性的名字,其值对应着6.1.7.1中定义的。另外,任何字段都是可以缺省的。属性描述符的标示字面量标记是"PropertyDescriptor"
属性描述符的值又可以进一步分为数据属性描述符合访问器属性描述符。这取决于其使用或者存在的字段。一个数据属性描述符拥有[[Value]]、[[Writable]]。一个访问器描述符拥有[[Get]]、[[Set]]。任何一个属性描述符都有[[Enumerable]]和[[Configurable]].一个属性描述符不可能既是数据属性描述符又是访问器属性描述符,也可能不是其中任何一种。一个通用的属性描述符就两者都不是。一个拥有表1或者表2中全部字段的属性描述符就是其中一种。
下面的抽象操作是在属性描述符上进行操作的:
6.2.4.1 IsAccessorDescriptor ( Desc )
其执行步骤如下:
- 如果 Desc is undefined, 返回 false.
- 如果 Desc.[[Get]] 和 Desc.[[Set]] 都是缺省的, 返回 false.
- 返回 true.
6.2.4.2 IsDataDescriptor ( Desc )
其执行步骤如下:
- 如果 Desc 是 undefined, 返回 false.
- 如果 Desc.[[Value]] 和 Desc.[[Writable]] 都是缺省的, 返回 false.
- 返回 true.
6.2.4.3 IsGenericDescriptor ( Desc )
其执行步骤如下:
- 如果 Desc 是 undefined, 返回 false.
- 如果 IsAccessorDescriptor(Desc) 和 IsDataDescriptor(Desc) 都是 false, 返回 true.
- 返回 false.
6.2.4.4 FromPropertyDescriptor ( Desc )
其执行步骤如下:
- 如果 Desc is undefined, return undefined.
- 使 obj 为 ObjectCreate(%ObjectPrototype%).
- 断言: obj 是没有自身属性的可扩展的原始对象
- 如果 Desc 有 [[Value]] 字段, 那么:
- 执行 CreateDataProperty(obj, "value", Desc.[[Value]]).
- 如果 Desc 有 [[Writable]] 字段, 那么
- 执行 CreateDataProperty(obj, "writable", Desc.[[Writable]]).
- 如果 Desc 有 [[Get]] 字段, 那么
- 执行 CreateDataProperty(obj, "get", Desc.[[Get]]).
- 如果 Desc 有 [[Set]] 字段, 那么
- 执行 CreateDataProperty(obj, "设置", Desc.[[Set]]).
- 如果 Desc 有 [[Enumerable]] 字段, 那么
- 执行 CreateDataProperty(obj, "enumerable", Desc.[[Enumerable]]).
- 如果 Desc 有 [[Configurable]] 字段, 那么
- 执行 CreateDataProperty(obj, "configurable", Desc.[[Configurable]]).
- 断言: 上面所有的 CreateDataProperty 操作返回 true.
- 返回 obj.
6.2.4.5 ToPropertyDescriptor ( Obj )
其执行步骤如下:
- 如果 Type(Obj) 不是 Object, 抛出 TypeError 异常.
- 使 desc 为新的 Property Descriptor 没有字段
- 使 hasEnumerable 为 ? HasProperty(Obj, "enumerable").
- 如果 hasEnumerable is true, 那么
- 使 enum 为 ToBoolean(? Get(Obj, "enumerable")).
- 设置desc的 [[Enumerable]] 字段值为 enum.
- 使 hasConfigurable 为 ? HasProperty(Obj, "configurable").
- 如果 hasConfigurable 为 true, 那么
- 使 conf 为 ToBoolean(? Get(Obj, "configurable")).
- 设置desc的 [[Configurable]] 字段为 conf.
- 使 hasValue 为 ? HasProperty(Obj, "value").
- 如果 hasValue is true, 那么
- 使 value 为 ? Get(Obj, "value").
- 设置desc的 [[Value]] 字段为 value.
- 使 hasWritable 为 ? HasProperty(Obj, "writable").
- 如果 hasWritable is true, 那么
- 使 writable 为 ToBoolean(? Get(Obj, "writable")).
- 设置desc的 [[Writable]] 字段为 writable.
- 使 hasGet 为 ? HasProperty(Obj, "get").
- 如果 hasGet 是 true, 那么
- 使 getter 为 ? Get(Obj, "get").
- 如果 IsCallable(getter) 是 false 并且 getter 不是undefined, 抛出 TypeError 异常.
- 设置desc的 [[Get]] 字段为 getter.
- 使 hasSet 为 ? HasProperty(Obj, "设置").
- 如果 hasSet is true, 那么
- 使 setter 为 ? Get(Obj, "设置").
- 如果 IsCallable(setter) 是false并且 setter 不是undefined, 抛出 TypeError 异常.
- 设置desc的 [[Set]] 字段为 setter.
- 如果 desc.[[Get]] 或者 desc.[[Set]] 存在, 那么
- desc.[[Value]] 或者 desc.[[Writable]] 存在, 抛出 TypeError 异常.
- 返回 desc.
6.2.4.6 CompletePropertyDescriptor ( Desc )
其执行步骤如下:
- 断言: Desc 是 Property Descriptor.
- 使 like 为 Record{[[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false}.
- 如果 IsGenericDescriptor(Desc) 或者 IsDataDescriptor(Desc) 是 true, 那么
- 如果 Desc 没有 [[Value]] 字段, 设置 Desc.[[Value]] 为 like.[[Value]].
- 如果 Desc 没有 [[Writable]] 字段, 设置 Desc.[[Writable]] 为 like.[[Writable]].
- 否则,
- 如果 Desc 没有 [[Get]] 字段, 设置 Desc.[[Get]] 为 like.[[Get]].
- 如果 Desc 没有 [[Set]] 字段, 设置 Desc.[[Set]] 为 like.[[Set]].
- 如果 Desc 没有 [[Enumerable]] 字段, 设置 Desc.[[Enumerable]] 为 like.[[Enumerable]].
- 如果 Desc 没有 [[Configurable]] 字段, 设置 Desc.[[Configurable]] 为 like.[[Configurable]].
- 返回 Desc.
6.2.5 词法环境和词法环境记录项规范类型
词法环境和环境记录项类型用来解释函数和代码块中获取名称的过程。这些类型和操作在8.1中定义
6.2.6 数据块(Data Block)
数据块类型是用来描述一组唯一的可变的数值。一个数据块的值是由字节数组创建的,并且初始值是0
为了便于在规范中使用数据块,类数组的语法就能使用在数据块类型上。它也是从0开始索引的,比如db是5个字节组成的数据块,db[2]就是其第三个字节
下面的抽象操作是用在数据块上的
6.2.6.1 CreateByteDataBlock (size)
其执行步骤如下:
- 断言: size ≥ 0.
- 使 db 是新的有size个字节的 Data Block 如果没法创建这样的一个Data Block,抛出 RangeError 异常.
- 设置db的所有字节为 0.
- 返回 db.
6.2.6.2 CopyDataBlockBytes (toBlock, toIndex, fromBlock, fromIndex, count)
其执行步骤如下:
- 断言: fromBlock and toBlock 是不同的 Data Block values.
- 断言: fromIndex, toIndex, count 是>=0的整数.
- 使 fromSize 为 fromBlock的字节数.
- 断言: fromIndex+count ≤ fromSize.
- 使 toSize 为 toBlock的字节数.
- 断言: toIndex+count ≤ toSize.
- 只要 count>0 重复下面的步骤
- 设置 toBlock[toIndex] 的值为 fromBlock[fromIndex].
- toIndex和fromIndex各自加1.
- count减一.
- 返回 NormalCompletion(empty).