Skip to content

Commit 5727ac0

Browse files
committed
Address review comments
1 parent 6c9e570 commit 5727ac0

File tree

2 files changed

+42
-58
lines changed

2 files changed

+42
-58
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,9 @@ Exactly how to implement the subsequence search algorithm is intended to be left
5353

5454
The `needle` argument can be:
5555

56-
* A **TypedArray of the same element type** as the haystack — its element values are extracted directly.
57-
* A **different-type TypedArray** — coerced via its `@@iterator` method, with each element converted to the haystack's element type (just like any other iterable).
58-
* An **iterable object** (other than a String) — its elements are collected and converted to the haystack's element type, then searched for.
59-
* A **String** — throws a `TypeError`. Although strings are iterable, their iteration yields code points, which is unlikely to be the intended behavior when searching a TypedArray.
56+
* A **TypedArray** (same or different element type) — iterated via its `@@iterator` method. Each yielded value must be the correct type for the haystack (Number for non-BigInt TypedArrays, BigInt for BigInt TypedArrays); if any value is the wrong type, the search returns `-1`. This creates a snapshot of the needle's elements, which is necessary for correctness when the needle is backed by a SharedArrayBuffer.
57+
* An **iterable object** (other than a String) — its elements are collected and type-checked against the haystack's element type. If any element is the wrong type, the search returns `-1`.
58+
* A **String** — throws a `TypeError`. Although strings are iterable, their iteration yields code points, which is unlikely to be the intended behaviour when searching a TypedArray.
6059
* Any other value — throws a `TypeError`.
6160

6261
```js
@@ -68,7 +67,7 @@ u8.search(new Uint8Array([3, 4])); // 2
6867
// Iterable (e.g. plain Array)
6968
u8.search([3, 4]); // 2
7069

71-
// Different-type TypedArray (coerced via iteration)
70+
// Different-type TypedArray (iterated via @@iterator)
7271
u8.search(new Int16Array([3, 4])); // 2
7372

7473
// String throws

spec.emu

Lines changed: 38 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ contributors: James M Snell
1818
<emu-clause id="sec-abstract-operations-for-typedarray-objects">
1919
<h1>Abstract Operations for TypedArray Objects</h1>
2020

21-
<emu-clause id="sec-validateintegralnumberoffset" type="abstract operation">
21+
<emu-clause id="sec-validateintegralnumber" type="abstract operation">
2222
<h1>
23-
ValidateIntegralNumberOffset (
23+
ValidateIntegralNumber (
2424
_value_: an ECMAScript language value,
2525
_default_: an integer,
2626
): either a normal completion containing an integer or a throw completion
@@ -38,29 +38,6 @@ contributors: James M Snell
3838
</emu-alg>
3939
</emu-clause>
4040

41-
<emu-clause id="sec-iterabletotypedarrayelementlist" type="abstract operation">
42-
<h1>
43-
IterableToTypedArrayElementList (
44-
_iterable_: an Object,
45-
_iteratorMethod_: a function object,
46-
_elementType_: a TypedArray element type,
47-
): either a normal completion containing either a List of Numbers or a List of BigInts, or a throw completion
48-
</h1>
49-
<dl class="header">
50-
<dt>description</dt>
51-
<dd>It iterates _iterable_ using _iteratorMethod_ and coerces each element to the appropriate numeric type for _elementType_, returning the results as a List.</dd>
52-
</dl>
53-
<emu-alg>
54-
1. Let _values_ be ? IteratorToList(? GetIteratorFromMethod(_iterable_, _iteratorMethod_)).
55-
1. Let _result_ be a new empty List.
56-
1. For each element _v_ of _values_, do
57-
1. If IsBigIntElementType(_elementType_) is *true*, let _numValue_ be ? ToBigInt(_v_).
58-
1. Else, let _numValue_ be ? ToNumber(_v_).
59-
1. Append _numValue_ to _result_.
60-
1. Return _result_.
61-
</emu-alg>
62-
</emu-clause>
63-
6441
<emu-clause id="sec-sequencesamevaluezeroequal" type="abstract operation">
6542
<h1>
6643
SequenceSameValueZeroEqual (
@@ -84,31 +61,39 @@ contributors: James M Snell
8461
</emu-alg>
8562
</emu-clause>
8663

87-
<emu-clause id="sec-coercetocompatibletypedarrayelementlist" type="abstract operation">
64+
<emu-clause id="sec-tocompatibletypedarrayelementlist" type="abstract operation">
8865
<h1>
89-
CoerceToCompatibleTypedArrayElementList (
66+
ToCompatibleTypedArrayElementList (
9067
_O_: a TypedArray,
9168
_needle_: an ECMAScript language value,
92-
): either a normal completion containing either a TypedArray, a List of Numbers, or a List of BigInts, or a throw completion
69+
): either a normal completion containing either a List of Numbers, a List of BigInts, or ~not-found~, or a throw completion
9370
</h1>
9471
<dl class="header">
9572
<dt>description</dt>
96-
<dd>It produces a sequence of element values compatible with _O_ from _needle_. If _needle_ is a same-type TypedArray, it is returned directly. If _needle_ is an iterable Object, its elements are collected, coerced to the element type of _O_, and returned as a List. Non-Object values (including Strings, which would otherwise be boxed into iterable String objects) and non-iterable Objects throw a *TypeError*.</dd>
73+
<dd>It produces a List of element values compatible with _O_ from _needle_. If _needle_ is an iterable Object, its elements are collected and validated against the element type of _O_. If any element is not the expected type, ~not-found~ is returned. Non-Object values (including Strings, which would otherwise be boxed into iterable String objects) and non-iterable Objects throw a *TypeError*.</dd>
9774
</dl>
9875
<emu-alg>
99-
1. If _needle_ is an Object, then
100-
1. If _needle_ has a [[TypedArrayName]] internal slot and TypedArrayElementType(_O_) is TypedArrayElementType(_needle_), return _needle_.
101-
1. Let _iteratorMethod_ be ? GetMethod(_needle_, @@iterator).
102-
1. If _iteratorMethod_ is not *undefined*, return ? IterableToTypedArrayElementList(_needle_, _iteratorMethod_, TypedArrayElementType(_O_)).
103-
1. Throw a *TypeError* exception.
104-
1. Else,
105-
1. Throw a *TypeError* exception.
76+
1. If _needle_ is not an Object, throw a *TypeError* exception.
77+
1. Let _iteratorMethod_ be ? GetMethod(_needle_, @@iterator).
78+
1. If _iteratorMethod_ is *undefined*, throw a *TypeError* exception.
79+
1. Let _values_ be ? IteratorToList(? GetIteratorFromMethod(_needle_, _iteratorMethod_)).
80+
1. Let _elementType_ be TypedArrayElementType(_O_).
81+
1. Let _result_ be a new empty List.
82+
1. For each element _v_ of _values_, do
83+
1. If IsBigIntElementType(_elementType_) is *true*, then
84+
1. If _v_ is not a BigInt, return ~not-found~.
85+
1. Else,
86+
1. If _v_ is not a Number, return ~not-found~.
87+
1. Append _v_ to _result_.
88+
1. Return _result_.
10689
</emu-alg>
10790
<emu-note>
108-
<p>When _needle_ is a same-type TypedArray, it is returned directly. A different-type TypedArray is coerced via its @@iterator method like any other iterable, with each element converted to the element type of _O_.</p>
91+
<p>All TypedArray needles (whether same-type or different-type) are iterated via their @@iterator method. This ensures that the resulting List is a snapshot of the needle's elements at the time of the call, which is necessary for correctness when the needle is backed by a SharedArrayBuffer (see <a href="https://github.com/tc39/proposal-typedarray-findwithin/issues/8">issue #8</a>).</p>
92+
<p>If the iterable yields values of the wrong type (e.g., BigInts when the haystack is a non-BigInt TypedArray, or Numbers when it is a BigInt TypedArray), ~not-found~ is returned rather than throwing. Such values can never SameValueZero-match any element of the haystack, so returning ~not-found~ (which callers interpret as *-1*<sub>𝔽</sub>) is the correct result without the cost of performing the search. Alternatively we could
93+
throw a TypeError in these cases.</p>
10994
</emu-note>
11095
<emu-note type="editor">
111-
<p>The acceptance of iterable objects as needles is intended to improve ergonomics (see <a href="https://github.com/tc39/proposal-typedarray-findwithin/issues/1">issue #1</a>). String primitives are not Objects and so fall through to the *TypeError* in the final step. Non-iterable objects and non-String primitives also throw to avoid silent misuse (see <a href="https://github.com/tc39/proposal-typedarray-findwithin/issues/7">issue #7</a>).</p>
96+
<p>The acceptance of iterable objects as needles is intended to improve ergonomics (see <a href="https://github.com/tc39/proposal-typedarray-findwithin/issues/1">issue #1</a>). String primitives are not Objects and so fall through to the *TypeError* in the first step. Non-iterable objects and non-String primitives also throw to avoid silent misuse (see <a href="https://github.com/tc39/proposal-typedarray-findwithin/issues/7">issue #7</a>).</p>
11297
</emu-note>
11398
</emu-clause>
11499

@@ -117,7 +102,7 @@ contributors: James M Snell
117102
TypedArraySearchSubsequence (
118103
_O_: a TypedArray,
119104
_haystackLength_: a non-negative integer,
120-
_needle_: either a TypedArray, a List of Numbers, or a List of BigInts,
105+
_needle_: either a List of Numbers or a List of BigInts,
121106
_direction_: ~first~ or ~last~,
122107
_position_: a non-negative integer,
123108
): an integral Number
@@ -136,12 +121,9 @@ contributors: James M Snell
136121
1. If _needleLength_ &gt; _haystackLength_, return *-1*<sub>𝔽</sub>.
137122
1. [id="step-search-last"] Return the largest integer _k_ such that _k_ ≤ _position_ and _k_ + _needleLength_ ≤ _haystackLength_ and SequenceSameValueZeroEqual(the List of elements of _O_ from index _k_ to _k_ + _needleLength_ - 1, _needle_) is *true*, or *-1*<sub>𝔽</sub> if no such _k_ exists.
138123
</emu-alg>
139-
<emu-note type="editor">
140-
<p>The description of the subsequence search in <emu-xref href="#step-search-first"></emu-xref> and <emu-xref href="#step-search-last"></emu-xref> is intentionally high-level, allowing implementations freedom in how the search is performed. A question for committee is whether these steps need to be specified more precisely with explicit algorithmic substeps (e.g., element-by-element comparison with specific iteration order), even if implementations are expected to use optimized approaches such as Boyer-Moore or other string matching algorithms.</p>
141-
</emu-note>
142124
<emu-note>
143-
<p>The _needle_ is produced by CoerceToCompatibleTypedArrayElementList, which ensures element values are compatible with the element type of _O_. When _needle_ is a same-type TypedArray, it qualifies as a List of Numbers or a List of BigInts for the purposes of SequenceSameValueZeroEqual. Subsequence equality is determined by SequenceSameValueZeroEqual.</p>
144-
<p>Implementations may use any technique to search for the subsequence, such as naive search, Boyer-Moore, or other string matching algorithms, provided the observable result is correct.</p>
125+
<p>The _needle_ is produced by ToCompatibleTypedArrayElementList, which validates that element values are the correct type for _O_ and are a snapshot that cannot be modified during the search. The elements of _O_ (the haystack) are not snapshotted, consistent with how %TypedArray%.prototype.indexOf and %TypedArray%.prototype.lastIndexOf scan the haystack directly. When _O_ is backed by a SharedArrayBuffer, another agent may modify elements of _O_ during the search.</p>
126+
<p>Implementations may use any technique to search for the subsequence, such as naive search, Boyer-Moore, or other matching algorithms, provided the observable result is correct.</p>
145127
</emu-note>
146128
</emu-clause>
147129
</emu-clause>
@@ -155,11 +137,12 @@ contributors: James M Snell
155137
<emu-alg>
156138
1. Let _O_ be the *this* value.
157139
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
158-
1. Let _coerced_ be ? CoerceToCompatibleTypedArrayElementList(_O_, _needle_).
140+
1. Let _needleList_ be ? ToCompatibleTypedArrayElementList(_O_, _needle_).
141+
1. If _needleList_ is ~not-found~, return *-1*<sub>𝔽</sub>.
159142
1. Let _haystackLength_ be TypedArrayLength(_taRecord_).
160-
1. Let _n_ be ? ValidateIntegralNumberOffset(_position_, 0).
143+
1. Let _n_ be ? ValidateIntegralNumber(_position_, 0).
161144
1. Let _startFrom_ be the result of clamping _n_ between 0 and _haystackLength_.
162-
1. Return TypedArraySearchSubsequence(_O_, _haystackLength_, _coerced_, ~first~, _startFrom_).
145+
1. Return TypedArraySearchSubsequence(_O_, _haystackLength_, _needleList_, ~first~, _startFrom_).
163146
</emu-alg>
164147
</emu-clause>
165148

@@ -169,11 +152,12 @@ contributors: James M Snell
169152
<emu-alg>
170153
1. Let _O_ be the *this* value.
171154
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
172-
1. Let _coerced_ be ? CoerceToCompatibleTypedArrayElementList(_O_, _needle_).
155+
1. Let _needleList_ be ? ToCompatibleTypedArrayElementList(_O_, _needle_).
156+
1. If _needleList_ is ~not-found~, return *-1*<sub>𝔽</sub>.
173157
1. Let _haystackLength_ be TypedArrayLength(_taRecord_).
174-
1. Let _n_ be ? ValidateIntegralNumberOffset(_position_, _haystackLength_ - 1).
158+
1. Let _n_ be ? ValidateIntegralNumber(_position_, _haystackLength_ - 1).
175159
1. Let _startFrom_ be the result of clamping _n_ between 0 and _haystackLength_ - 1.
176-
1. Return TypedArraySearchSubsequence(_O_, _haystackLength_, _coerced_, ~last~, _startFrom_).
160+
1. Return TypedArraySearchSubsequence(_O_, _haystackLength_, _needleList_, ~last~, _startFrom_).
177161
</emu-alg>
178162
</emu-clause>
179163

@@ -183,11 +167,12 @@ contributors: James M Snell
183167
<emu-alg>
184168
1. Let _O_ be the *this* value.
185169
1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~).
186-
1. Let _coerced_ be ? CoerceToCompatibleTypedArrayElementList(_O_, _needle_).
170+
1. Let _needleList_ be ? ToCompatibleTypedArrayElementList(_O_, _needle_).
171+
1. If _needleList_ is ~not-found~, return *false*.
187172
1. Let _haystackLength_ be TypedArrayLength(_taRecord_).
188-
1. Let _n_ be ? ValidateIntegralNumberOffset(_position_, 0).
173+
1. Let _n_ be ? ValidateIntegralNumber(_position_, 0).
189174
1. Let _startFrom_ be the result of clamping _n_ between 0 and _haystackLength_.
190-
1. Let _index_ be TypedArraySearchSubsequence(_O_, _haystackLength_, _coerced_, ~first~, _startFrom_).
175+
1. Let _index_ be TypedArraySearchSubsequence(_O_, _haystackLength_, _needleList_, ~first~, _startFrom_).
191176
1. If _index_ is *-1*<sub>𝔽</sub>, return *false*.
192177
1. Return *true*.
193178
</emu-alg>

0 commit comments

Comments
 (0)