From a623bfb94e9d5088bd7d60709832c71bac487bbe Mon Sep 17 00:00:00 2001 From: Michael Dyck Date: Thu, 23 Feb 2023 09:52:57 -0800 Subject: [PATCH] Editorial: Factor out FindViaPredicate (#2898) ... from: - Array.prototype.find - Array.prototype.findIndex - Array.prototype.findLast - Array.prototype.findLastIndex - %TypedArray%.prototype.find - %TypedArray%.prototype.findIndex - %TypedArray%.prototype.findLast - %TypedArray%.prototype.findLastIndex --- esmeta-ignore.json | 1 + spec.html | 152 ++++++++++++++++++--------------------------- 2 files changed, 61 insertions(+), 92 deletions(-) diff --git a/esmeta-ignore.json b/esmeta-ignore.json index b02191cc4b..69e12db5d5 100644 --- a/esmeta-ignore.json +++ b/esmeta-ignore.json @@ -22,6 +22,7 @@ "CreateIterResultObject", "ECMAScriptFunctionObject.Call", "ECMAScriptFunctionObject.Construct", + "FindViaPredicate", "FlattenIntoArray", "ForIn/OfBodyEvaluation", "FunctionBody[0,0].EvaluateFunctionBody", diff --git a/spec.html b/spec.html index 439e85c1a5..e0f4eb2ad1 100644 --- a/spec.html +++ b/spec.html @@ -37542,25 +37542,15 @@

Array.prototype.filter ( _callbackfn_ [ , _thisArg_ ] )

Array.prototype.find ( _predicate_ [ , _thisArg_ ] )

-

_predicate_ should be a function that accepts three arguments and returns a value that is coercible to a Boolean value. `find` calls _predicate_ once for each element of the array, in ascending order, until it finds one where _predicate_ returns *true*. If such an element is found, `find` immediately returns that element value. Otherwise, `find` returns *undefined*.

-

If a _thisArg_ parameter is provided, it will be used as the *this* value for each invocation of _predicate_. If it is not provided, *undefined* is used instead.

-

_predicate_ is called with three arguments: the value of the element, the index of the element, and the object being traversed.

-

`find` does not directly mutate the object on which it is called but the object may be mutated by the calls to _predicate_.

-

The range of elements processed by `find` is set before the first call to _predicate_. Elements that are appended to the array after the call to `find` begins will not be visited by _predicate_. If existing elements of the array are changed, their value as passed to _predicate_ will be the value at the time that `find` visits them; elements that are deleted after the call to `find` begins and before being visited are still visited and are either looked up from the prototype or are *undefined*.

+

This method calls _predicate_ once for each element of the array, in ascending index order, until it finds one where _predicate_ returns a value that coerces to *true*. If such an element is found, `find` immediately returns that element value. Otherwise, `find` returns *undefined*.

+

See FindViaPredicate for additional information.

This method performs the following steps when called:

1. Let _O_ be ? ToObject(*this* value). 1. Let _len_ be ? LengthOfArrayLike(_O_). - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ? Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return _kValue_. - 1. Set _k_ to _k_ + 1. - 1. Return *undefined*. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~ascending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Value]].

This method is intentionally generic; it does not require that its *this* value be an Array. Therefore it can be transferred to other kinds of objects for use as a method.

@@ -37570,25 +37560,15 @@

Array.prototype.find ( _predicate_ [ , _thisArg_ ] )

Array.prototype.findIndex ( _predicate_ [ , _thisArg_ ] )

-

_predicate_ should be a function that accepts three arguments and returns a value that is coercible to a Boolean value. `findIndex` calls _predicate_ once for each element of the array, in ascending order, until it finds one where _predicate_ returns *true*. If such an element is found, `findIndex` immediately returns the index of that element value. Otherwise, `findIndex` returns -1.

-

If a _thisArg_ parameter is provided, it will be used as the *this* value for each invocation of _predicate_. If it is not provided, *undefined* is used instead.

-

_predicate_ is called with three arguments: the value of the element, the index of the element, and the object being traversed.

-

`findIndex` does not directly mutate the object on which it is called but the object may be mutated by the calls to _predicate_.

-

The range of elements processed by `findIndex` is set before the first call to _predicate_. Elements that are appended to the array after the call to `findIndex` begins will not be visited by _predicate_. If existing elements of the array are changed, their value as passed to _predicate_ will be the value at the time that `findIndex` visits them; elements that are deleted after the call to `findIndex` begins and before being visited are still visited and are either looked up from the prototype or are *undefined*.

+

This method calls _predicate_ once for each element of the array, in ascending index order, until it finds one where _predicate_ returns a value that coerces to *true*. If such an element is found, `findIndex` immediately returns the index of that element value. Otherwise, `findIndex` returns -1.

+

See FindViaPredicate for additional information.

This method performs the following steps when called:

1. Let _O_ be ? ToObject(*this* value). 1. Let _len_ be ? LengthOfArrayLike(_O_). - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ? Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return 𝔽(_k_). - 1. Set _k_ to _k_ + 1. - 1. Return *-1*𝔽. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~ascending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Index]].

This method is intentionally generic; it does not require that its *this* value be an Array. Therefore it can be transferred to other kinds of objects for use as a method.

@@ -37598,25 +37578,15 @@

Array.prototype.findIndex ( _predicate_ [ , _thisArg_ ] )

Array.prototype.findLast ( _predicate_ [ , _thisArg_ ] )

-

_predicate_ should be a function that accepts three arguments and returns a value that is coercible to a Boolean value. `findLast` calls _predicate_ once for each element of the array, in descending index order, until it finds one where _predicate_ returns *true*. If such an element is found, `findLast` immediately returns that element value. Otherwise, `findLast` returns *undefined*.

-

If a _thisArg_ parameter is provided, it will be used as the *this* value for each invocation of _predicate_. If it is not provided, *undefined* is used instead.

-

_predicate_ is called with three arguments: the element, the index of the element in the array, and the object being traversed.

-

`findLast` does not directly mutate the object on which it is called but the object may be mutated by the calls to _predicate_.

-

The range of elements processed by `findLast` is set before the first call to _predicate_. Elements that are appended to the array after the call to `findLast` begins will not be visited by _predicate_. If existing elements of the array are changed, their value as passed to _predicate_ will be the value at the time that `findLast` visits them.

+

This method calls _predicate_ once for each element of the array, in descending index order, until it finds one where _predicate_ returns a value that coerces to *true*. If such an element is found, `findLast` immediately returns that element value. Otherwise, `findLast` returns *undefined*.

+

See FindViaPredicate for additional information.

This method performs the following steps when called:

1. Let _O_ be ? ToObject(*this* value). 1. Let _len_ be ? LengthOfArrayLike(_O_). - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be _len_ - 1. - 1. Repeat, while _k_ ≥ 0, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ? Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return _kValue_. - 1. Set _k_ to _k_ - 1. - 1. Return *undefined*. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~descending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Value]].

This method 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.

@@ -37626,29 +37596,55 @@

Array.prototype.findLast ( _predicate_ [ , _thisArg_ ] )

Array.prototype.findLastIndex ( _predicate_ [ , _thisArg_ ] )

-

_predicate_ should be a function that accepts three arguments and returns a value that is coercible to a Boolean value. `findLastIndex` calls _predicate_ once for each element of the array, in descending index order, until it finds one where _predicate_ returns *true*. If such an element is found, `findLastIndex` immediately returns the index of that element value. Otherwise, `findLastIndex` returns -1.

-

If a _thisArg_ parameter is provided, it will be used as the *this* value for each invocation of _predicate_. If it is not provided, *undefined* is used instead.

-

_predicate_ is called with three arguments: the element, the index of the element in the array, and the object being traversed.

-

`findLastIndex` does not directly mutate the object on which it is called but the object may be mutated by the calls to _predicate_.

-

The range of elements processed by `findLastIndex` is set before the first call to _predicate_. Elements that are appended to the array after the call to `findLastIndex` begins will not be visited by _predicate_. If existing elements of the array are changed, their value as passed to _predicate_ will be the value at the time that `findLastIndex` visits them.

+

This method calls _predicate_ once for each element of the array, in descending index order, until it finds one where _predicate_ returns a value that coerces to *true*. If such an element is found, `findLastIndex` immediately returns the index of that element value. Otherwise, `findLastIndex` returns -1.

+

See FindViaPredicate for additional information.

This method performs the following steps when called:

1. Let _O_ be ? ToObject(*this* value). 1. Let _len_ be ? LengthOfArrayLike(_O_). - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be _len_ - 1. - 1. Repeat, while _k_ ≥ 0, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ? Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return 𝔽(_k_). - 1. Set _k_ to _k_ - 1. - 1. Return *-1*𝔽. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~descending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Index]].

This method 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.

+ + +

+ FindViaPredicate ( + _O_: an Object, + _len_: a non-negative integer, + _direction_: ~ascending~ or ~descending~, + _predicate_: an ECMAScript language value, + _thisArg_: an ECMAScript language value, + ): either a normal completion containing a Record with fields [[Index]] (an integral Number) and [[Value]] (an ECMAScript language value) or a throw completion +

+
+
description
+
+

_O_ should be an array-like object or a TypedArray. This operation calls _predicate_ once for each element of _O_, in either ascending index order or descending index order (as indicated by _direction_), until it finds one where _predicate_ returns a value that coerces to *true*. At that point, this operation returns a Record that gives the index and value of the element found. If no such element is found, this operation returns a Record that specifies *-1*𝔽 for the index and *undefined* for the value.

+

_predicate_ should be a function. When called for an element of the array, it is passed three arguments: the value of the element, the index of the element, and the object being traversed. Its return value will be coerced to a Boolean value.

+

_thisArg_ will be used as the *this* value for each invocation of _predicate_.

+

This operation does not directly mutate the object on which it is called, but the object may be mutated by the calls to _predicate_.

+

The range of elements processed is set before the first call to _predicate_, just before the traversal begins. Elements that are appended to the array after this will not be visited by _predicate_. If existing elements of the array are changed, their value as passed to _predicate_ will be the value at the time that this operation visits them. Elements that are deleted after traversal begins and before being visited are still visited and are either looked up from the prototype or are *undefined*.

+
+
+ + 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. + 1. If _direction_ is ~ascending~, then + 1. Let _indices_ be a List of the integers in the interval from 0 (inclusive) to _len_ (exclusive), in ascending order. + 1. Else, + 1. Let _indices_ be a List of the integers in the interval from 0 (inclusive) to _len_ (exclusive), in descending order. + 1. For each integer _k_ of _indices_, do + 1. Let _Pk_ be ! ToString(𝔽(_k_)). + 1. NOTE: If _O_ is a TypedArray, the following invocation of Get will return a normal completion. + 1. Let _kValue_ be ? Get(_O_, _Pk_). + 1. Let _testResult_ be ? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »). + 1. If ToBoolean(_testResult_) is *true*, return the Record { [[Index]]: 𝔽(_k_), [[Value]]: _kValue_ }. + 1. Return the Record { [[Index]]: *-1*𝔽, [[Value]]: *undefined* }. + +
@@ -39110,15 +39106,8 @@

%TypedArray%.prototype.find ( _predicate_ [ , _thisArg_ ] )

1. Let _O_ be the *this* value. 1. Perform ? ValidateTypedArray(_O_). 1. Let _len_ be _O_.[[ArrayLength]]. - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return _kValue_. - 1. Set _k_ to _k_ + 1. - 1. Return *undefined*. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~ascending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Value]].

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

@@ -39131,15 +39120,8 @@

%TypedArray%.prototype.findIndex ( _predicate_ [ , _thisArg_ ] )

1. Let _O_ be the *this* value. 1. Perform ? ValidateTypedArray(_O_). 1. Let _len_ be _O_.[[ArrayLength]]. - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return 𝔽(_k_). - 1. Set _k_ to _k_ + 1. - 1. Return *-1*𝔽. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~ascending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Index]].

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

@@ -39152,15 +39134,8 @@

%TypedArray%.prototype.findLast ( _predicate_ [ , _thisArg_ ] )

1. Let _O_ be the *this* value. 1. Perform ? ValidateTypedArray(_O_). 1. Let _len_ be _O_.[[ArrayLength]]. - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be _len_ - 1. - 1. Repeat, while _k_ ≥ 0, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return _kValue_. - 1. Set _k_ to _k_ - 1. - 1. Return *undefined*. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~descending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Value]].

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

@@ -39173,15 +39148,8 @@

%TypedArray%.prototype.findLastIndex ( _predicate_ [ , _thisArg_ ] )

1. Let _O_ be the *this* value. 1. Perform ? ValidateTypedArray(_O_). 1. Let _len_ be _O_.[[ArrayLength]]. - 1. If IsCallable(_predicate_) is *false*, throw a *TypeError* exception. - 1. Let _k_ be _len_ - 1. - 1. Repeat, while _k_ ≥ 0, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _testResult_ be ToBoolean(? Call(_predicate_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _testResult_ is *true*, return 𝔽(_k_). - 1. Set _k_ to _k_ - 1. - 1. Return *-1*𝔽. + 1. Let _findRec_ be ? FindViaPredicate(_O_, _len_, ~descending~, _predicate_, _thisArg_). + 1. Return _findRec_.[[Index]].

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.