Skip to content

Commit fa71a1e

Browse files
committed
feat!: distinguish between signed zeros
This commit refactors the implementation to rely on the same value algorithm, rather than strict equality. Previously, we treated NaN values as equal, which follows the same value algorithm; however, we did not distinguish between signed zeros. This commit ensures that we follow the same value algorithm fully. BREAKING CHANGE: distinguish signed zeros To migrate, users should normalize signed zeros before invoking this function. Otherwise, users should use a different algorithm which uses strict equality to determine "sameness" (e.g., a package such as `@stdlib/array/base/includes`). --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: na - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 6dc5ea7 commit fa71a1e

File tree

5 files changed

+67
-61
lines changed

5 files changed

+67
-61
lines changed

lib/node_modules/@stdlib/assert/contains/README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ limitations under the License.
1818
1919
-->
2020

21-
# Contains
21+
# contains
2222

2323
> Test if an array-like value contains a search value.
2424
@@ -36,16 +36,23 @@ limitations under the License.
3636
var contains = require( '@stdlib/assert/contains' );
3737
```
3838

39-
#### contains( val, searchValue\[, position] )
39+
#### contains( value, searchValue\[, position] )
4040

41-
Tests if `val` contains a search value. When `val` is a `string`, the function checks whether the characters of a search string are found in the input string.
41+
Tests if `value` contains a search value.
42+
43+
```javascript
44+
var v = contains( [ 1, 2, 3 ], 2 );
45+
// returns true
46+
```
47+
48+
When `value` is a string, the function checks whether the characters of a search string are found in the input string.
4249

4350
```javascript
4451
var v = contains( 'Hello World', 'World' );
4552
// returns true
4653
```
4754

48-
When `val` is an `array-like` object, but not a `string`, the function checks whether the input value contains an element strictly equal to the specified search value.
55+
When `value` is an array-like object, but not a string, the function checks whether the input value contains an element which is the [same value][@stdlib/assert/is-same-value] as the specified search value.
4956

5057
```javascript
5158
var arr = [ null, NaN, 2, 'abc', {} ];
@@ -77,7 +84,7 @@ v = contains( [ true, NaN, false ], true, 1 );
7784
// returns false
7885
```
7986

80-
If not provided an `array-like` object, the function throws an error.
87+
If not provided an array-like object, the function throws an error.
8188

8289
<!-- run throws: true -->
8390

@@ -105,8 +112,8 @@ var v = contains( 'hello', 'e', 2.5 );
105112

106113
## Notes
107114

108-
- For `strings`, the function is modeled after [String.prototype.includes][mdn-includes], part of the ECMAScript 6 specification. This function is different from a call to `String.prototype.includes.call` insofar as type-checking is performed for all arguments.
109-
- The function does **not** distinguish between positive and negative zero.
115+
- For strings, the function is modeled after [String.prototype.includes][mdn-includes], part of the ECMAScript 6 specification. This function is different from a call to `String.prototype.includes.call` insofar as type-checking is performed for all arguments.
116+
- The function **does** distinguish between positive and negative zero (see [`@stdlib/assert/is-same-value`][@stdlib/assert/is-same-value].
110117
- If `position < 0`, the search is performed for the entire input array or string.
111118

112119
</section>
@@ -159,6 +166,8 @@ bool = contains( 'Hidden Treasures', '' );
159166

160167
[mdn-includes]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
161168

169+
[@stdlib/assert/is-same-value]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/assert/is-same-value
170+
162171
</section>
163172

164173
<!-- /.links -->

lib/node_modules/@stdlib/assert/contains/docs/repl.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11

2-
{{alias}}( val, searchValue[, position] )
2+
{{alias}}( value, searchValue[, position] )
33
Tests if an array-like value contains a search value.
44

5-
When `val` is a string, the function checks whether the characters of the
5+
When `value` is a string, the function checks whether the characters of the
66
search string are found in the input string. The search is case-sensitive.
77

8-
When `val` is an array-like object, the function checks whether the input
8+
When `value` is an array-like object, the function checks whether the input
99
array contains an element strictly equal to the specified search value.
1010

1111
For strings, this function is modeled after `String.prototype.includes`,
1212
part of the ECMAScript 6 specification. This function is different from a
1313
call to `String.prototype.includes.call` insofar as type-checking is
1414
performed for all arguments.
1515

16-
The function does not distinguish between positive and negative zero.
16+
The function does distinguish between positive and negative zero.
1717

1818
If `position < 0`, the search is performed for the entire input array or
1919
string.
2020

2121

2222
Parameters
2323
----------
24-
val: ArrayLike
24+
value: ArrayLike
2525
Input value.
2626

2727
searchValue: any

lib/node_modules/@stdlib/assert/contains/docs/types/index.d.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ import { ArrayLike } from '@stdlib/types/array';
2727
*
2828
* ## Notes
2929
*
30-
* - When `val` is a string, the function checks whether the characters of the search string are found in the input string. The search is case-sensitive.
31-
* - When `val` is an array-like object, the function checks whether the input array contains an element strictly equal to the specified search value.
30+
* - When `value` is a string, the function checks whether the characters of the search string are found in the input string. The search is case-sensitive.
31+
* - When `value` is an array-like object, the function checks whether the input array contains an element which is the same as the specified search value.
3232
* - For strings, this function is modeled after `String.prototype.includes`, part of the ECMAScript 6 specification. This function is different from a call to `String.prototype.includes.call` insofar as type-checking is performed for all arguments.
33-
* - The function does not distinguish between positive and negative zero.
33+
* - The function does distinguish between positive and negative zero.
3434
* - If `position < 0`, the search is performed for the entire input array or string.
3535
*
36-
* @param val - input value
36+
* @param value - input value
3737
* @param searchValue - search value
3838
* @param position - position at which to start searching for `searchValue` (default: 0)
3939
* @throws second argument must be a primitive string primitive when the first argument is a string
@@ -67,7 +67,7 @@ import { ArrayLike } from '@stdlib/types/array';
6767
* var bool = contains( 'Hidden Treasures', '' );
6868
* // returns true
6969
*/
70-
declare function contains( val: ArrayLike<any>, searchValue: any, position?: number ): boolean;
70+
declare function contains( value: ArrayLike<unknown>, searchValue: unknown, position?: number ): boolean;
7171

7272

7373
// EXPORTS //

lib/node_modules/@stdlib/assert/contains/lib/main.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
var isCollection = require( '@stdlib/assert/is-collection' );
2424
var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;
2525
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
26-
var isnan = require( '@stdlib/assert/is-nan' ).isPrimitive;
26+
var isSameValue = require( '@stdlib/assert/is-same-value' );
2727
var format = require( '@stdlib/string/format' );
2828

2929

@@ -32,7 +32,7 @@ var format = require( '@stdlib/string/format' );
3232
/**
3333
* Tests if an array-like value contains a search value.
3434
*
35-
* @param {(Collection|string)} val - input value
35+
* @param {(Collection|string)} value - input value
3636
* @param {*} searchValue - search value
3737
* @param {integer} [position=0] - position at which to start searching for `searchValue`
3838
* @throws {TypeError} first argument must be array-like
@@ -69,12 +69,15 @@ var format = require( '@stdlib/string/format' );
6969
* var bool = contains( 'Hidden Treasures', '' );
7070
* // returns true
7171
*/
72-
function contains( val, searchValue, position ) {
72+
function contains( value, searchValue, position ) {
73+
var isStr;
7374
var len;
7475
var pos;
7576
var i;
76-
if ( !isCollection( val ) && !isString( val ) ) {
77-
throw new TypeError( format( 'invalid argument. First argument must be array-like. Value: `%s`.', val ) );
77+
78+
isStr = isString( value );
79+
if ( !isCollection( value ) && !isStr ) {
80+
throw new TypeError( format( 'invalid argument. First argument must be array-like. Value: `%s`.', value ) );
7881
}
7982
if ( arguments.length < 2 ) {
8083
throw new Error( 'insufficient arguments. Must provide a search value.' );
@@ -90,23 +93,15 @@ function contains( val, searchValue, position ) {
9093
} else {
9194
pos = 0;
9295
}
93-
if ( isString( val ) ) {
96+
if ( isStr ) {
9497
if ( !isString( searchValue ) ) {
9598
throw new TypeError( format( 'invalid argument. Second argument must be a string. Value: `%s`.', searchValue ) );
9699
}
97-
return val.indexOf( searchValue, pos ) !== -1;
98-
}
99-
len = val.length;
100-
if ( isnan( searchValue ) ) {
101-
for ( i = pos; i < len; i++ ) {
102-
if ( isnan( val[ i ] ) ) {
103-
return true;
104-
}
105-
}
106-
return false;
100+
return value.indexOf( searchValue, pos ) !== -1;
107101
}
102+
len = value.length;
108103
for ( i = pos; i < len; i++ ) {
109-
if ( val[ i ] === searchValue ) {
104+
if ( isSameValue( value[ i ], searchValue ) ) {
110105
return true;
111106
}
112107
}

lib/node_modules/@stdlib/assert/contains/test/test.js

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ tape( 'the function returns `true` when a search string is contained in input st
129129
var out;
130130

131131
out = contains( 'Hello World', 'World' );
132-
t.equal( out, true, 'returns true' );
132+
t.equal( out, true, 'returns expected value' );
133133

134134
out = contains( 'Hello World', ' ' );
135-
t.equal( out, true, 'returns true' );
135+
t.equal( out, true, 'returns expected value' );
136136

137137
out = contains( 'Hello World', 'Hell' );
138-
t.equal( out, true, 'returns true' );
138+
t.equal( out, true, 'returns expected value' );
139139

140140
t.end();
141141
});
@@ -144,13 +144,13 @@ tape( 'the function returns `false` when a search string is not contained in inp
144144
var out;
145145

146146
out = contains( 'Hello World', 'world' );
147-
t.equal( out, false, 'returns false' );
147+
t.equal( out, false, 'returns expected value' );
148148

149149
out = contains( 'Hello World', '\t' );
150-
t.equal( out, false, 'returns false' );
150+
t.equal( out, false, 'returns expected value' );
151151

152152
out = contains( 'Hello World', 'Word' );
153-
t.equal( out, false, 'returns false' );
153+
t.equal( out, false, 'returns expected value' );
154154

155155
t.end();
156156
});
@@ -159,13 +159,13 @@ tape( 'the function returns `true` when a search value is contained in input arr
159159
var out;
160160

161161
out = contains( [ NaN, null, 3, 'abc' ], 'abc' );
162-
t.equal( out, true, 'returns true' );
162+
t.equal( out, true, 'returns expected value' );
163163

164164
out = contains( [ NaN, null, 3, 'abc' ], NaN );
165-
t.equal( out, true, 'returns true' );
165+
t.equal( out, true, 'returns expected value' );
166166

167167
out = contains( [ NaN, null, 3, 'abc' ], null );
168-
t.equal( out, true, 'returns true' );
168+
t.equal( out, true, 'returns expected value' );
169169

170170
t.end();
171171
});
@@ -174,13 +174,13 @@ tape( 'the function returns `false` when search value is not contained in input
174174
var out;
175175

176176
out = contains( [ NaN, null, 3, 'abc' ], 'ac' );
177-
t.equal( out, false, 'returns false' );
177+
t.equal( out, false, 'returns expected value' );
178178

179179
out = contains( [ NaN, null, 3, 'abc' ], false );
180-
t.equal( out, false, 'returns false' );
180+
t.equal( out, false, 'returns expected value' );
181181

182182
out = contains( [ NaN, null, 3, 'abc' ], 3.5 );
183-
t.equal( out, false, 'returns false' );
183+
t.equal( out, false, 'returns expected value' );
184184

185185
t.end();
186186
});
@@ -189,48 +189,50 @@ tape( 'the function supports beginning a search at the specified position', func
189189
var out;
190190

191191
out = contains( 'ABCDEFG', 'A', 1 );
192-
t.equal( out, false, 'returns false' );
192+
t.equal( out, false, 'returns expected value' );
193193

194194
out = contains( 'ABCDEFG', 'B', 1 );
195-
t.equal( out, true, 'returns true' );
195+
t.equal( out, true, 'returns expected value' );
196196

197197
out = contains( 'ABCDEFG', 'A', -3 );
198-
t.equal( out, true, 'returns true' );
198+
t.equal( out, true, 'returns expected value' );
199199

200200
out = contains( [ null, NaN, 2 ], 3, 1 );
201-
t.equal( out, false, 'returns false' );
201+
t.equal( out, false, 'returns expected value' );
202202

203203
out = contains( [ null, NaN, 2 ], NaN, 1 );
204-
t.equal( out, true, 'returns true' );
204+
t.equal( out, true, 'returns expected value' );
205205

206206
out = contains( [ null, NaN, 2 ], NaN, -3 );
207-
t.equal( out, true, 'returns true' );
207+
t.equal( out, true, 'returns expected value' );
208208

209209
out = contains( [ null, NaN, 2 ], NaN, 2 );
210-
t.equal( out, false, 'returns false' );
210+
t.equal( out, false, 'returns expected value' );
211211

212212
t.end();
213213
});
214214

215215
tape( 'the function returns `true` if provided an input string and an empty string as the search value', function test( t ) {
216-
t.equal( contains( 'abc', '' ), true, 'returns true' );
217-
t.equal( contains( '', '' ), true, 'returns true' );
216+
t.equal( contains( 'abc', '' ), true, 'returns expected value' );
217+
t.equal( contains( '', '' ), true, 'returns expected value' );
218218
t.end();
219219
});
220220

221221
tape( 'the function returns `false` if provided an empty array-like value', function test( t ) {
222-
t.equal( contains( [], '' ), false, 'returns false' );
222+
t.equal( contains( [], '' ), false, 'returns expected value' );
223223
t.end();
224224
});
225225

226-
tape( 'the function does not distinguish between positive and negative zero', function test( t ) {
227-
t.equal( contains( [ -0.0 ], +0.0 ), true, 'returns true' );
228-
t.equal( contains( [ +0.0 ], -0.0 ), true, 'returns true' );
226+
tape( 'the function does distinguish between positive and negative zero', function test( t ) {
227+
t.equal( contains( [ -0.0 ], +0.0 ), false, 'returns expected value' );
228+
t.equal( contains( [ +0.0 ], -0.0 ), false, 'returns expected value' );
229+
t.equal( contains( [ -0.0 ], -0.0 ), true, 'returns expected value' );
230+
t.equal( contains( [ +0.0 ], +0.0 ), true, 'returns expected value' );
229231
t.end();
230232
});
231233

232234
tape( 'the function returns `false` if provided a position which exceeds the maximum index', function test( t ) {
233-
t.equal( contains( [ 1 ], 1, 1e5 ), false, 'returns false' );
234-
t.equal( contains( 'abc', 'a', 1e5 ), false, 'returns false' );
235+
t.equal( contains( [ 1 ], 1, 1e5 ), false, 'returns expected value' );
236+
t.equal( contains( 'abc', 'a', 1e5 ), false, 'returns expected value' );
235237
t.end();
236238
});

0 commit comments

Comments
 (0)