Skip to content

Commit

Permalink
Editorial: Factor out SortArrayLike
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdyck committed Feb 11, 2021
1 parent 88df3ed commit 8934240
Showing 1 changed file with 66 additions and 57 deletions.
123 changes: 66 additions & 57 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -32508,63 +32508,8 @@ <h1>Array.prototype.sort ( _comparefn_ )</h1>
1. Let _ySmaller_ be the result of performing Abstract Relational Comparison _yString_ &lt; _xString_.
1. If _ySmaller_ is *true*, return *1*<sub>𝔽</sub>.
1. Return *+0*<sub>𝔽</sub>.
1. Let _items_ be a new empty List.
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kPresent_ be ? HasProperty(_obj_, _Pk_).
1. If _kPresent_ is *true*, then
1. Let _kValue_ be ? Get(_obj_, _Pk_).
1. Append _kValue_ to _items_.
1. Set _k_ to _k_ + 1.
1. Let _itemCount_ be the number of elements in _items_.
1. [id="step-array-sort"] Sort _items_ using an implementation-defined sequence of calls to _SortCompare_. If any such call returns an abrupt completion, stop before performing any further calls to _SortCompare_ or steps in this algorithm and return that completion.
1. Let _j_ be 0.
1. Repeat, while _j_ &lt; _itemCount_,
1. Perform ? Set(_obj_, ! ToString(𝔽(_j_)), _items_[_j_], *true*).
1. Set _j_ to _j_ + 1.
1. Repeat, while _j_ &lt; _len_,
1. Perform ? DeletePropertyOrThrow(_obj_, ! ToString(𝔽(_j_))).
1. Set _j_ to _j_ + 1.
1. Return _obj_.
1. Return ? SortArrayLike(_obj_, _len_, _SortCompare_).
</emu-alg>
<p>The <em>sort order</em> is the ordering of _items_ after completion of step <emu-xref href="#step-array-sort"></emu-xref> of the algorithm above. If _SortCompare_ is not a consistent comparator for the elements of _items_ (see below), the sort order is implementation-defined. Otherwise, the sort order must satisfy all of the following conditions:</p>
<ul>
<li>
There must be some mathematical permutation &pi; of the non-negative integers less than _itemCount_, such that for every non-negative integer _j_ less than _itemCount_, the element <emu-eqn>old[_j_]</emu-eqn> is exactly the same as <emu-eqn>new[&pi;(_j_)]</emu-eqn>.
</li>
<li>
Then for all non-negative integers _j_ and _k_, each less than _itemCount_, if <emu-eqn>_SortCompare_(old[_j_], old[_k_]) &lt; 0</emu-eqn>, then <emu-eqn>&pi;(_j_) &lt; &pi;(_k_)</emu-eqn>.
</li>
</ul>
<p>Here the notation <emu-eqn>old[_j_]</emu-eqn> is used to refer to <emu-eqn>_items_[_j_]</emu-eqn> before step <emu-xref href="#step-array-sort"></emu-xref> is executed, and the notation <emu-eqn>new[_j_]</emu-eqn> to refer to <emu-eqn>_items_[_j_]</emu-eqn> after step <emu-xref href="#step-array-sort"></emu-xref> has been executed.</p>
<p>An abstract closure or function _comparator_ is a <dfn>consistent comparator</dfn> for a set of values _S_ if all of the requirements below are met for all values _a_, _b_, and _c_ (possibly the same value) in the set _S_: The notation <emu-eqn>_a_ &lt;<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) &lt; 0</emu-eqn>; <emu-eqn>_a_ =<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) = 0</emu-eqn> (of either sign); and <emu-eqn>_a_ &gt;<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) &gt; 0</emu-eqn>.</p>
<ul>
<li>
Calling _comparator_(_a_, _b_) always returns the same value _v_ when given a specific pair of values _a_ and _b_ as its two arguments. Furthermore, Type(_v_) is Number, and _v_ is not *NaN*. Note that this implies that exactly one of _a_ &lt;<sub>C</sub> _b_, _a_ =<sub>C</sub> _b_, and _a_ &gt;<sub>C</sub> _b_ will be true for a given pair of _a_ and _b_.
</li>
<li>
Calling _comparator_(_a_, _b_) does not modify _obj_ or any object on _obj_'s prototype chain.
</li>
<li>
_a_ =<sub>C</sub> _a_ (reflexivity)
</li>
<li>
If _a_ =<sub>C</sub> _b_, then _b_ =<sub>C</sub> _a_ (symmetry)
</li>
<li>
If _a_ =<sub>C</sub> _b_ and _b_ =<sub>C</sub> _c_, then _a_ =<sub>C</sub> _c_ (transitivity of =<sub>C</sub>)
</li>
<li>
If _a_ &lt;<sub>C</sub> _b_ and _b_ &lt;<sub>C</sub> _c_, then _a_ &lt;<sub>C</sub> _c_ (transitivity of &lt;<sub>C</sub>)
</li>
<li>
If _a_ &gt;<sub>C</sub> _b_ and _b_ &gt;<sub>C</sub> _c_, then _a_ &gt;<sub>C</sub> _c_ (transitivity of &gt;<sub>C</sub>)
</li>
</ul>
<emu-note>
<p>The above conditions are necessary and sufficient to ensure that _comparator_ divides the set _S_ into equivalence classes and that these equivalence classes are totally ordered.</p>
</emu-note>
<emu-note>
<p>Because non-existent property values always compare greater than *undefined* property values, and *undefined* always compares greater than any other value, *undefined* property values always sort to the end of the result, followed by non-existent property values.</p>
</emu-note>
Expand All @@ -32586,6 +32531,69 @@ <h1>Array.prototype.sort ( _comparefn_ )</h1>
<emu-note>
<p>The `sort` function is intentionally generic; it does not require that its *this* value be an Array object. Therefore, it can be transferred to other kinds of objects for use as a method.</p>
</emu-note>

<emu-clause id="sec-sortarraylike" aoid="SortArrayLike">
<h1>SortArrayLike ( _obj_, _len_, _SortCompare_ )</h1>
<p>The abstract operation SortArrayLike takes arguments _obj_ (an array-like object), _len_ (a non-negative integer), and _SortCompare_ (an Abstract Closure with two parameters). It performs the following steps when called:</p>
<emu-alg>
1. Let _items_ be a new empty List.
1. Let _k_ be 0.
1. Repeat, while _k_ &lt; _len_,
1. Let _Pk_ be ! ToString(𝔽(_k_)).
1. Let _kPresent_ be ? HasProperty(_obj_, _Pk_).
1. If _kPresent_ is *true*, then
1. Let _kValue_ be ? Get(_obj_, _Pk_).
1. Append _kValue_ to _items_.
1. Set _k_ to _k_ + 1.
1. Let _itemCount_ be the number of elements in _items_.
1. [id="step-array-sort"] Sort _items_ using an implementation-defined sequence of calls to _SortCompare_. If any such call returns an abrupt completion, stop before performing any further calls to _SortCompare_ or steps in this algorithm and return that completion.
1. Let _j_ be 0.
1. Repeat, while _j_ &lt; _itemCount_,
1. Perform ? Set(_obj_, ! ToString(𝔽(_j_)), _items_[_j_], *true*).
1. Set _j_ to _j_ + 1.
1. Repeat, while _j_ &lt; _len_,
1. Perform ? DeletePropertyOrThrow(_obj_, ! ToString(𝔽(_j_))).
1. Set _j_ to _j_ + 1.
1. Return _obj_.
</emu-alg>
<p>The <em>sort order</em> is the ordering of _items_ after completion of step <emu-xref href="#step-array-sort"></emu-xref> of the algorithm above. If _SortCompare_ is not a consistent comparator for the elements of _items_ (see below), the sort order is implementation-defined. Otherwise, the sort order must satisfy all of the following conditions:</p>
<ul>
<li>
There must be some mathematical permutation &pi; of the non-negative integers less than _itemCount_, such that for every non-negative integer _j_ less than _itemCount_, the element <emu-eqn>old[_j_]</emu-eqn> is exactly the same as <emu-eqn>new[&pi;(_j_)]</emu-eqn>.
</li>
<li>
Then for all non-negative integers _j_ and _k_, each less than _itemCount_, if <emu-eqn>_SortCompare_(old[_j_], old[_k_]) &lt; 0</emu-eqn>, then <emu-eqn>&pi;(_j_) &lt; &pi;(_k_)</emu-eqn>.
</li>
</ul>
<p>Here the notation <emu-eqn>old[_j_]</emu-eqn> is used to refer to <emu-eqn>_items_[_j_]</emu-eqn> before step <emu-xref href="#step-array-sort"></emu-xref> is executed, and the notation <emu-eqn>new[_j_]</emu-eqn> to refer to <emu-eqn>_items_[_j_]</emu-eqn> after step <emu-xref href="#step-array-sort"></emu-xref> has been executed.</p>
<p>An abstract closure or function _comparator_ is a <dfn>consistent comparator</dfn> for a set of values _S_ if all of the requirements below are met for all values _a_, _b_, and _c_ (possibly the same value) in the set _S_: The notation <emu-eqn>_a_ &lt;<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) &lt; 0</emu-eqn>; <emu-eqn>_a_ =<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) = 0</emu-eqn> (of either sign); and <emu-eqn>_a_ &gt;<sub>C</sub> _b_</emu-eqn> means <emu-eqn>_comparator_(_a_, _b_) &gt; 0</emu-eqn>.</p>
<ul>
<li>
Calling _comparator_(_a_, _b_) always returns the same value _v_ when given a specific pair of values _a_ and _b_ as its two arguments. Furthermore, Type(_v_) is Number, and _v_ is not *NaN*. Note that this implies that exactly one of _a_ &lt;<sub>C</sub> _b_, _a_ =<sub>C</sub> _b_, and _a_ &gt;<sub>C</sub> _b_ will be true for a given pair of _a_ and _b_.
</li>
<li>
Calling _comparator_(_a_, _b_) does not modify _obj_ or any object on _obj_'s prototype chain.
</li>
<li>
_a_ =<sub>C</sub> _a_ (reflexivity)
</li>
<li>
If _a_ =<sub>C</sub> _b_, then _b_ =<sub>C</sub> _a_ (symmetry)
</li>
<li>
If _a_ =<sub>C</sub> _b_ and _b_ =<sub>C</sub> _c_, then _a_ =<sub>C</sub> _c_ (transitivity of =<sub>C</sub>)
</li>
<li>
If _a_ &lt;<sub>C</sub> _b_ and _b_ &lt;<sub>C</sub> _c_, then _a_ &lt;<sub>C</sub> _c_ (transitivity of &lt;<sub>C</sub>)
</li>
<li>
If _a_ &gt;<sub>C</sub> _b_ and _b_ &gt;<sub>C</sub> _c_, then _a_ &gt;<sub>C</sub> _c_ (transitivity of &gt;<sub>C</sub>)
</li>
</ul>
<emu-note>
<p>The above conditions are necessary and sufficient to ensure that _comparator_ divides the set _S_ into equivalence classes and that these equivalence classes are totally ordered.</p>
</emu-note>
</emu-clause>
</emu-clause>

<emu-clause id="sec-array.prototype.splice">
Expand Down Expand Up @@ -33648,7 +33656,7 @@ <h1>%TypedArray%.prototype.some ( _callbackfn_ [ , _thisArg_ ] )</h1>
<h1>%TypedArray%.prototype.sort ( _comparefn_ )</h1>
<p>%TypedArray%`.prototype.sort` is a distinct function 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 the %TypedArray%`.prototype.sort` specification may be optimized with the knowledge that the *this* value is an object that has a fixed length and whose <emu-xref href="#integer-index">integer-indexed</emu-xref> properties are not sparse.</p>
<p>This function is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
<p>Upon entry, the following steps are performed to initialize evaluation of the `sort` function. These steps are used instead of steps <emu-xref href="#step-array-sort-comparefn"></emu-xref>–<emu-xref href="#step-array-sort-len"></emu-xref> in <emu-xref href="#sec-array.prototype.sort"></emu-xref>:</p>
<p>The following steps are performed:</p>
<emu-alg>
1. If _comparefn_ is not *undefined* and IsCallable(_comparefn_) is *false*, throw a *TypeError* exception.
1. Let _obj_ be the *this* value.
Expand All @@ -33670,6 +33678,7 @@ <h1>%TypedArray%.prototype.sort ( _comparefn_ )</h1>
1. If _x_ is *-0*<sub>𝔽</sub> and _y_ is *+0*<sub>𝔽</sub>, return *-1*<sub>𝔽</sub>.
1. If _x_ is *+0*<sub>𝔽</sub> and _y_ is *-0*<sub>𝔽</sub>, return *1*<sub>𝔽</sub>.
1. Return *+0*<sub>𝔽</sub>.
1. Return ? SortArrayLike(_obj_, _len_, _SortCompare_).
</emu-alg>
<emu-note>
<p>Because *NaN* always compares greater than any other value, *NaN* property values always sort to the end of the result when _comparefn_ is not provided.</p>
Expand Down

0 comments on commit 8934240

Please sign in to comment.