title: Reflect.isTemplateObject
stage: 2
copyright: false
contributors: Mike Samuel, Krzysztof Kotowicz, Jordan Harband, Daniel Ehrenberg

Ordinary and Exotic Objects Behaviours

Built-in Exotic Object Internal Methods and Slots

Array Exotic Objects

ArrayCreate ( _length_: a non-negative integer, optional _proto_: an Object, ): either a normal completion containing an Array exotic object or a throw completion

description
It is used to specify the creation of new Arrays.
skip global checks
true
To enable the new API, this proposal modifies ArrayCreate to add an internal slot to each array. 1. If _length_ > 232 - 1, throw a *RangeError* exception. 1. If _proto_ is not present, set _proto_ to %Array.prototype%. 1. Let _A_ be MakeBasicObject(« [[Prototype]], [[Extensible]], [[TemplateObject]] »). 1. Set _A_.[[Prototype]] to _proto_. 1. Set _A_.[[TemplateObject]] to *false*. 1. Set _A_.[[DefineOwnProperty]] as specified in . 1. Perform ! OrdinaryDefineOwnProperty(_A_, *"length"*, PropertyDescriptor { [[Value]]: 𝔽(_length_), [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false* }). 1. Return _A_.

ECMAScript Language: Expressions

Primary Expression

Template Literals

GetTemplateObject ( _templateLiteral_: a Parse Node, ): an Array

To enable the new API, this proposal modifies GetTemplateObject to change the value of the new internal slot. 1. Let _realm_ be the current Realm Record. 1. Let _templateRegistry_ be _realm_.[[TemplateMap]]. 1. For each element _e_ of _templateRegistry_, do 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then 1. Return _e_.[[Array]]. 1. Let _rawStrings_ be the TemplateStrings of _templateLiteral_ with argument *true*. 1. Assert: _rawStrings_ is a List of Strings. 1. Let _cookedStrings_ be the TemplateStrings of _templateLiteral_ with argument *false*. 1. Let _count_ be the number of elements in the List _cookedStrings_. 1. Assert: _count_ ≤ 232 - 1. 1. Let _template_ be ! ArrayCreate(_count_). 1. Set _template_.[[TemplateObject]] to *true*. 1. Let _rawObj_ be ! ArrayCreate(_count_). 1. Let _index_ be 0. 1. Repeat, while _index_ < _count_, 1. Let _prop_ be ! ToString(𝔽(_index_)). 1. Let _cookedValue_ be _cookedStrings_[_index_]. 1. Perform ! DefinePropertyOrThrow(_template_, _prop_, PropertyDescriptor { [[Value]]: _cookedValue_, [[Writable]]: *false*, [[Enumerable]]: *true*, [[Configurable]]: *false* }). 1. Let _rawValue_ be the String value _rawStrings_[_index_]. 1. Perform ! DefinePropertyOrThrow(_rawObj_, _prop_, PropertyDescriptor { [[Value]]: _rawValue_, [[Writable]]: *false*, [[Enumerable]]: *true*, [[Configurable]]: *false* }). 1. Set _index_ to _index_ + 1. 1. Perform ! SetIntegrityLevel(_rawObj_, ~frozen~). 1. Perform ! DefinePropertyOrThrow(_template_, *"raw"*, PropertyDescriptor { [[Value]]: _rawObj_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }). 1. Perform ! SetIntegrityLevel(_template_, ~frozen~). 1. Append the Record { [[Site]]: _templateLiteral_, [[Array]]: _template_ } to _realm_.[[TemplateMap]]. 1. Return _template_.

The creation of a template object cannot result in an abrupt completion.

Each |TemplateLiteral| in the program code of a realm is associated with a unique template object that is used in the evaluation of tagged Templates (). The template objects are frozen and the same template object is used each time a specific tagged Template is evaluated. Whether template objects are created lazily upon first evaluation of the |TemplateLiteral| or eagerly prior to first evaluation is an implementation choice that is not observable to ECMAScript code.

Future editions of this specification may define additional non-enumerable properties of template objects.

Reflection

The Reflect Object

Reflect.isTemplateObject ( _value_ )

When the `isTemplateObject` method is called with argument _value_ the following steps are taken:

1. If ? IsArray(_value_) is *true* and _value_.[[TemplateObject]] is *true*, then 1. Return *true*. 1. Return *false*.

IsTemplateObject is realm-agnostic. Since template objects are frozen before escaping GetTemplateObject, testing (IsTemplateObject(_x_) and _x_.[[Prototype]] is the _realm_'s %Array.prototype%) is sufficient to determine whether an _x_ is a template object in a particular _realm_.

In user code, `Reflect.isTemplateObject(x) && x instanceof Array` is an equivalent test, assuming no changes to builtins.