Skip to content

Normative: Account for TypedArraySpeciesCreate species lookup #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 6, 2025
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions spec.emu
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,81 @@ contributors: Mark S. Miller, Richard Gibson
<emu-clause id="sec-typedarray-objects" number="2">
<h1>TypedArray Objects</h1>

<emu-clause id="sec-properties-of-the-%typedarray%-intrinsic-object" number="2">
<h1>Properties of the %TypedArray% Intrinsic Object</h1>
<p>The %TypedArray% intrinsic object:</p>
<ul>
<li>has a [[Prototype]] internal slot whose value is %Function.prototype%.</li>
<li>has a *"name"* property whose value is *"TypedArray"*.</li>
<li>has the following properties:</li>
</ul>

<emu-clause id="sec-%typedarray%.from">
<h1>%TypedArray%.from ( _source_ [ , _mapper_ [ , _thisArg_ ] ] )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _C_ be the *this* value.
1. If IsConstructor(_C_) is *false*, throw a *TypeError* exception.
1. If _mapper_ is *undefined*, then
1. Let _mapping_ be *false*.
1. Else,
1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception.
1. Let _mapping_ be *true*.
1. Let _usingIterator_ be ? GetMethod(_source_, %Symbol.iterator%).
1. If _usingIterator_ is not *undefined*, then
1. Let _values_ be ? IteratorToList(? GetIteratorFromMethod(_source_, _usingIterator_)).
1. Let _len_ be the number of elements in _values_.
1. Let _targetObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) »<ins>, ~write~</ins>).
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kValue_ be the first element of _values_.
1. Remove the first element from _values_.
1. If _mapping_ is *true*, then
1. Let _mappedValue_ be ? Call(_mapper_, _thisArg_, « _kValue_, 𝔽(_k_) »).
1. Else,
1. Let _mappedValue_ be _kValue_.
1. Perform ? Set(_targetObj_, _Pk_, _mappedValue_, *true*).
1. Set _k_ to _k_ + 1.
1. Assert: _values_ is now an empty List.
1. Return _targetObj_.
1. NOTE: _source_ is not an iterable object, so assume it is already an array-like object.
1. Let _arrayLike_ be ! ToObject(_source_).
1. Let _len_ be ? LengthOfArrayLike(_arrayLike_).
1. Let _targetObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) »<ins>, ~write~</ins>).
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kValue_ be ? Get(_arrayLike_, _Pk_).
1. If _mapping_ is *true*, then
1. Let _mappedValue_ be ? Call(_mapper_, _thisArg_, « _kValue_, 𝔽(_k_) »).
1. Else,
1. Let _mappedValue_ be _kValue_.
1. Perform ? Set(_targetObj_, _Pk_, _mappedValue_, *true*).
1. Set _k_ to _k_ + 1.
1. Return _targetObj_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-%typedarray%.of">
<h1>%TypedArray%.of ( ..._items_ )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _len_ be the number of elements in _items_.
1. Let _C_ be the *this* value.
1. If IsConstructor(_C_) is *false*, throw a *TypeError* exception.
1. Let _newObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) »<ins>, ~write~</ins>).
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _kValue_ be _items_[_k_].
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Perform ? Set(_newObj_, _Pk_, _kValue_, *true*).
1. Set _k_ to _k_ + 1.
1. Return _newObj_.
</emu-alg>
</emu-clause>
</emu-clause>

<emu-clause id="sec-properties-of-the-%typedarrayprototype%-object" number="3">
<h1>Properties of the %TypedArray% Prototype Object</h1>

Expand Down Expand Up @@ -262,6 +337,58 @@ contributors: Mark S. Miller, Richard Gibson
</emu-alg>
</emu-clause>

<emu-clause id="sec-%typedarray%.prototype.filter" number="10">
<h1>%TypedArray%.prototype.filter ( _callback_ [ , _thisArg_ ] )</h1>
<p>The interpretation and use of the arguments of this method are the same as for `Array.prototype.filter` as defined in <emu-xref href="#sec-array.prototype.filter"></emu-xref>.</p>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
1. Let _len_ be TypedArrayLength(_taRecord_).
1. If IsCallable(_callback_) is *false*, throw a *TypeError* exception.
1. Let _kept_ be a new empty List.
1. Let _captured_ be 0.
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kValue_ be ! Get(_O_, _Pk_).
1. Let _selected_ be ToBoolean(? Call(_callback_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)).
1. If _selected_ is *true*, then
1. Append _kValue_ to _kept_.
1. Set _captured_ to _captured_ + 1.
1. Set _k_ to _k_ + 1.
1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_captured_) »<ins>, ~write~</ins>).
1. Let _n_ be 0.
1. For each element _e_ of _kept_, do
1. Perform ! Set(_A_, ! ToString(𝔽(_n_)), _e_, *true*).
1. Set _n_ to _n_ + 1.
1. Return _A_.
</emu-alg>
<p>This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
</emu-clause>

<emu-clause id="sec-%typedarray%.prototype.map" number="22">
<h1>%TypedArray%.prototype.map ( _callback_ [ , _thisArg_ ] )</h1>
<p>The interpretation and use of the arguments of this method are the same as for `Array.prototype.map` as defined in <emu-xref href="#sec-array.prototype.map"></emu-xref>.</p>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
1. Let _len_ be TypedArrayLength(_taRecord_).
1. If IsCallable(_callback_) is *false*, throw a *TypeError* exception.
1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_len_) »<ins>, ~write~</ins>).
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kValue_ be ! Get(_O_, _Pk_).
1. Let _mappedValue_ be ? Call(_callback_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »).
1. Perform ? Set(_A_, _Pk_, _mappedValue_, *true*).
1. Set _k_ to _k_ + 1.
1. Return _A_.
</emu-alg>
<p>This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
</emu-clause>

<emu-clause id="sec-%typedarray%.prototype.reverse" number="25">
<h1>%TypedArray%.prototype.reverse ( )</h1>
<p>The interpretation and use of the arguments of this method are the same as for `Array.prototype.reverse` as defined in <emu-xref href="#sec-array.prototype.reverse"></emu-xref>.</p>
Expand Down Expand Up @@ -307,6 +434,59 @@ contributors: Mark S. Miller, Richard Gibson
<p>This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
</emu-clause>

<emu-clause id="sec-%typedarray%.prototype.slice" number="27">
<h1>%TypedArray%.prototype.slice ( _start_, _end_ )</h1>
<p>The interpretation and use of the arguments of this method are the same as for `Array.prototype.slice` as defined in <emu-xref href="#sec-array.prototype.slice"></emu-xref>.</p>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
1. Let _srcArrayLength_ be TypedArrayLength(_taRecord_).
1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_).
1. If _relativeStart_ = -∞, let _startIndex_ be 0.
1. Else if _relativeStart_ &lt; 0, let _startIndex_ be max(_srcArrayLength_ + _relativeStart_, 0).
1. Else, let _startIndex_ be min(_relativeStart_, _srcArrayLength_).
1. If _end_ is *undefined*, let _relativeEnd_ be _srcArrayLength_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_).
1. If _relativeEnd_ = -∞, let _endIndex_ be 0.
1. Else if _relativeEnd_ &lt; 0, let _endIndex_ be max(_srcArrayLength_ + _relativeEnd_, 0).
1. Else, let _endIndex_ be min(_relativeEnd_, _srcArrayLength_).
1. Let _countBytes_ be max(_endIndex_ - _startIndex_, 0).
1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_countBytes_) »<ins>, ~write~</ins>).
1. If _countBytes_ > 0, then
1. Set _taRecord_ to MakeTypedArrayWithBufferWitnessRecord(_O_, ~seq-cst~).
1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception.
1. Set _endIndex_ to min(_endIndex_, TypedArrayLength(_taRecord_)).
1. Set _countBytes_ to max(_endIndex_ - _startIndex_, 0).
1. Let _srcType_ be TypedArrayElementType(_O_).
1. Let _targetType_ be TypedArrayElementType(_A_).
1. If _srcType_ is _targetType_, then
1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
1. Let _srcBuffer_ be _O_.[[ViewedArrayBuffer]].
1. Let _targetBuffer_ be _A_.[[ViewedArrayBuffer]].
1. Let _elementSize_ be TypedArrayElementSize(_O_).
1. Let _srcByteOffset_ be _O_.[[ByteOffset]].
1. Let _srcByteIndex_ be (_startIndex_ × _elementSize_) + _srcByteOffset_.
1. Let _targetByteIndex_ be _A_.[[ByteOffset]].
1. Let _endByteIndex_ be _targetByteIndex_ + (_countBytes_ × _elementSize_).
1. Repeat, while _targetByteIndex_ &lt; _endByteIndex_,
1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, ~uint8~, *true*, ~unordered~).
1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, ~uint8~, _value_, *true*, ~unordered~).
1. Set _srcByteIndex_ to _srcByteIndex_ + 1.
1. Set _targetByteIndex_ to _targetByteIndex_ + 1.
1. Else,
1. Let _n_ be 0.
1. Let _k_ be _startIndex_.
1. Repeat, while _k_ &lt; _endIndex_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kValue_ be ! Get(_O_, _Pk_).
1. Perform ! Set(_A_, ! ToString(𝔽(_n_)), _kValue_, *true*).
1. Set _k_ to _k_ + 1.
1. Set _n_ to _n_ + 1.
1. Return _A_.
</emu-alg>
<p>This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
</emu-clause>

<emu-clause id="sec-%typedarray%.prototype.sort" oldids="sec-typedarraysortcompare" number="29">
<h1>%TypedArray%.prototype.sort ( _comparator_ )</h1>
<p>This is a distinct method that, except as described below, implements the same requirements as those of `Array.prototype.sort` as defined in <emu-xref href="#sec-array.prototype.sort"></emu-xref>. The implementation of this method may be optimized with the knowledge that the *this* value is an object that has a fixed length and whose integer-indexed properties are not sparse.</p>
Expand Down Expand Up @@ -336,6 +516,54 @@ contributors: Mark S. Miller, Richard Gibson
<emu-clause id="sec-abstract-operations-for-typedarray-objects" number="4">
<h1>Abstract Operations for TypedArray Objects</h1>

<emu-clause id="typedarray-species-create" type="abstract operation" number="1">
<h1>
TypedArraySpeciesCreate (
_exemplar_: a TypedArray,
_argumentList_: a List of ECMAScript language values,
<ins>optional _accessMode_: ~read~ or ~write~,</ins>
): either a normal completion containing a TypedArray or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It is used to specify the creation of a new TypedArray using a constructor function that is derived from _exemplar_. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray.</dd>
</dl>
<emu-alg>
1. <ins>If _accessMode_ is not present, set _accessMode_ to ~read~.</ins>
1. Let _defaultConstructor_ be the intrinsic object associated with the constructor name _exemplar_.[[TypedArrayName]] in <emu-xref href="#table-the-typedarray-constructors"></emu-xref>.
1. Let _constructor_ be ? SpeciesConstructor(_exemplar_, _defaultConstructor_).
1. Let _result_ be ? TypedArrayCreateFromConstructor(_constructor_, _argumentList_<ins>, _accessMode_</ins>).
1. <del>Assert: _result_ has [[TypedArrayName]] and [[ContentType]] internal slots.</del>
1. <ins>Assert: _result_ has all of the internal slots of a <var>TypedArray</var> instance (<emu-xref href="#sec-properties-of-typedarray-instances"></emu-xref>).</ins>
1. If _result_.[[ContentType]] is not _exemplar_.[[ContentType]], throw a *TypeError* exception.
1. Return _result_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-typedarraycreatefromconstructor" oldids="typedarray-create" type="abstract operation">
<h1>
TypedArrayCreateFromConstructor (
_constructor_: a constructor,
_argumentList_: a List of ECMAScript language values,
<ins>optional _accessMode_: ~read~ or ~write~,</ins>
): either a normal completion containing a TypedArray or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It is used to specify the creation of a new TypedArray using a constructor function.</dd>
</dl>
<emu-alg>
1. <ins>If _accessMode_ is not present, set _accessMode_ to ~read~.</ins>
1. Let _newTypedArray_ be ? Construct(_constructor_, _argumentList_).
1. Let _taRecord_ be ? ValidateTypedArray(_newTypedArray_, ~seq-cst~<ins>, _accessMode_</ins>).
1. If the number of elements in _argumentList_ is 1 and _argumentList_[0] is a Number, then
1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception.
1. Let _length_ be TypedArrayLength(_taRecord_).
1. If _length_ &lt; ℝ(_argumentList_[0]), throw a *TypeError* exception.
1. Return _newTypedArray_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-validatetypedarray" type="abstract operation" number="4">
<h1>
ValidateTypedArray (
Expand Down