-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add package: @wordpress/is-shallow-equal (#110)
* Add package: @wordpress/is-shallow-equal * Ignore benchmark for codecov No need to affect the codecoverage stats with a benchmarking script * Define benchmark dependencies as devDependencies Otherwise considered a proper required dependency from perspective of consuming project
- Loading branch information
Showing
9 changed files
with
411 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,6 @@ coverage: | |
|
||
comment: | ||
require_changes: true | ||
|
||
|
||
ignore: | ||
- "packages/is-shallow-equal/benchmark/*" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package-lock=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# @wordpress/is-shallow-equal | ||
|
||
A function for performing a shallow comparison between two objects or arrays. Two values have shallow equality when all of their members are strictly equal to the corresponding member of the other. | ||
|
||
## Usage | ||
|
||
The default export of `@wordpress/is-shallow-equal` is a function which accepts two objects or arrays: | ||
|
||
```js | ||
import isShallowEqual from '@wordpress/is-shallow-equal'; | ||
|
||
isShallowEqual( { a: 1 }, { a: 1, b: 2 } ); | ||
// ⇒ false | ||
|
||
isShallowEqual( { a: 1 }, { a: 1 } ); | ||
// ⇒ true | ||
|
||
isShallowEqual( [ 1 ], [ 1, 2 ] ); | ||
// ⇒ false | ||
|
||
isShallowEqual( [ 1 ], [ 1 ] ); | ||
// ⇒ true | ||
``` | ||
|
||
You can import a specific implementation if you already know the types of values you are working with: | ||
|
||
```js | ||
import isShallowEqualArrays from '@wordpress/is-shallow-equal/arrays'; | ||
import isShallowEqualObjects from '@wordpress/is-shallow-equal/objects'; | ||
``` | ||
|
||
## Rationale | ||
|
||
Shallow equality utilities are already a dime a dozen. Since these operations are often at the core of critical hot code paths, the WordPress contributors had specific requirements that were found to only be partially satisfied by existing solutions. | ||
|
||
In particular, it should… | ||
|
||
1. …consider non-primitive yet referentially-equal members values as equal. | ||
- Sorry, [`is-equal-shallow`](https://www.npmjs.com/package/is-equal-shallow). | ||
2. …offer a single function through which to interface, regardless of value type. | ||
- Sorry, [`shallow-equal`](https://www.npmjs.com/package/shallow-equal). | ||
3. …be barebones; only providing the basic functionality of shallow equality. | ||
- Sorry, [`shallow-equals`](https://www.npmjs.com/package/shallow-equals). | ||
4. …be intended for use in non-Facebook projects. | ||
- Sorry, [`fbjs/lib/shallowEqual`](https://www.npmjs.com/package/fbjs). | ||
5. …be the fastest implementation. | ||
- Sorry, _every other solution_. | ||
|
||
## Benchmarks | ||
|
||
The following results were produced under Node v9.10.1 on a MacBook Pro (Late 2016) 2.9 GHz Intel Core i7. The winner of each category is shown in bold. | ||
|
||
>**@wordpress/is-shallow-equal (object, equal) x 4,737,184 ops/sec ±0.41% (90 runs sampled)** | ||
>**@wordpress/is-shallow-equal (object, same) x 529,764,894 ops/sec ±0.61% (90 runs sampled)** | ||
>**@wordpress/is-shallow-equal (object, unequal) x 4,925,046 ops/sec ±0.55% (92 runs sampled)** | ||
>**@wordpress/is-shallow-equal (array, equal) x 65,801,336 ops/sec ±0.47% (90 runs sampled)** | ||
>**@wordpress/is-shallow-equal (array, same) x 540,194,917 ops/sec ±0.39% (93 runs sampled)** | ||
>**@wordpress/is-shallow-equal (array, unequal) x 35,380,873 ops/sec ±0.91% (89 runs sampled)** | ||
> | ||
>shallowequal (object, equal) x 3,290,410 ops/sec ±0.36% (93 runs sampled) | ||
>shallowequal (object, same) x 470,354,546 ops/sec ±0.61% (90 runs sampled) | ||
>shallowequal (object, unequal) x 3,552,560 ops/sec ±0.49% (92 runs sampled) | ||
>shallowequal (array, equal) x 1,499,613 ops/sec ±0.33% (90 runs sampled) | ||
>shallowequal (array, same) x 470,952,874 ops/sec ±0.36% (90 runs sampled) | ||
>shallowequal (array, unequal) x 1,518,756 ops/sec ±0.38% (93 runs sampled) | ||
> | ||
>shallow-equal (object, equal) x 4,691,935 ops/sec ±0.66% (90 runs sampled) | ||
>shallow-equal (object, same) x 516,007,655 ops/sec ±0.33% (91 runs sampled) | ||
>shallow-equal (object, unequal) x 4,892,693 ops/sec ±0.36% (92 runs sampled) | ||
>shallow-equal (array, equal) x 62,132,248 ops/sec ±0.35% (90 runs sampled) | ||
>shallow-equal (array, same) x 516,969,309 ops/sec ±0.36% (91 runs sampled) | ||
>shallow-equal (array, unequal) x 34,161,863 ops/sec ±0.87% (87 runs sampled) | ||
> | ||
>is-equal-shallow (object, equal) x 2,892,207 ops/sec ±0.45% (90 runs sampled) | ||
>is-equal-shallow (object, same) x 2,908,156 ops/sec ±0.32% (95 runs sampled) | ||
>is-equal-shallow (object, unequal) x 3,180,995 ops/sec ±0.36% (94 runs sampled) | ||
>is-equal-shallow (array, equal) x 1,105,943 ops/sec ±0.32% (91 runs sampled) | ||
>is-equal-shallow (array, same) x 1,104,462 ops/sec ±0.56% (93 runs sampled) | ||
>is-equal-shallow (array, unequal) x 1,773,097 ops/sec ±0.35% (92 runs sampled) | ||
> | ||
>shallow-equals (object, equal) x 4,400,657 ops/sec ±0.36% (93 runs sampled) | ||
>shallow-equals (object, same) x 4,422,178 ops/sec ±0.27% (92 runs sampled) | ||
>shallow-equals (object, unequal) x 4,705,010 ops/sec ±0.34% (94 runs sampled) | ||
>shallow-equals (array, equal) x 47,976,902 ops/sec ±0.67% (87 runs sampled) | ||
>shallow-equals (array, same) x 66,178,859 ops/sec ±0.62% (85 runs sampled) | ||
>shallow-equals (array, unequal) x 27,154,150 ops/sec ±0.70% (87 runs sampled) | ||
> | ||
>fbjs/lib/shallowEqual (object, equal) x 3,421,137 ops/sec ±0.36% (93 runs sampled) | ||
>fbjs/lib/shallowEqual (object, same) x 503,687,883 ops/sec ±0.40% (91 runs sampled) | ||
>fbjs/lib/shallowEqual (object, unequal) x 3,503,882 ops/sec ±0.68% (93 runs sampled) | ||
>fbjs/lib/shallowEqual (array, equal) x 1,510,797 ops/sec ±0.35% (90 runs sampled) | ||
>fbjs/lib/shallowEqual (array, same) x 245,713,360 ops/sec ±18.06% (48 runs sampled) | ||
>fbjs/lib/shallowEqual (array, unequal) x 1,515,645 ops/sec ±0.33% (92 runs sampled) | ||
You can run the benchmarks yourselves by cloning the repository, installing optional dependencies, and running the `benchmark/index.js` script: | ||
|
||
``` | ||
git clone https://github.com/WordPress/packages.git | ||
cd packages/packages/is-shallow-equal | ||
npm install --optional | ||
node benchmark | ||
``` | ||
|
||
<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require( './' ).isShallowEqualArrays; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const Benchmark = require( 'benchmark' ); | ||
|
||
const suite = new Benchmark.Suite; | ||
|
||
const beforeObject = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }; | ||
const afterObjectSame = beforeObject; | ||
const afterObjectEqual = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }; | ||
const afterObjectUnequal = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 'Unequal', g: 7 }; | ||
const beforeArray = [ 1, 2, 3, 4, 5, 6, 7 ]; | ||
const afterArraySame = beforeArray; | ||
const afterArrayEqual = [ 1, 2, 3, 4, 5, 6, 7 ]; | ||
const afterArrayUnequal = [ 1, 2, 3, 4, 5, 'Unequal', 7 ]; | ||
|
||
[ | ||
[ '@wordpress/is-shallow-equal', require( '../' ) ], | ||
[ 'shallowequal', require( 'shallowequal' ) ], | ||
[ 'shallow-equal', require( 'shallow-equal/objects' ), require( 'shallow-equal/arrays' ) ], | ||
[ 'is-equal-shallow', require( 'is-equal-shallow' ) ], | ||
[ 'shallow-equals', require( 'shallow-equals' ) ], | ||
[ 'fbjs/lib/shallowEqual', require( 'fbjs/lib/shallowEqual' ) ], | ||
].forEach( ( [ name, isShallowEqualObjects, isShallowEqualArrays = isShallowEqualObjects ] ) => { | ||
suite.add( name + ' (object, equal)', () => { | ||
isShallowEqualObjects( beforeObject, afterObjectEqual ); | ||
} ); | ||
|
||
suite.add( name + ' (object, same)', () => { | ||
isShallowEqualObjects( beforeObject, afterObjectSame ); | ||
} ); | ||
|
||
suite.add( name + ' (object, unequal)', () => { | ||
isShallowEqualObjects( beforeObject, afterObjectUnequal ); | ||
} ); | ||
|
||
suite.add( name + ' (array, equal)', () => { | ||
isShallowEqualArrays( beforeArray, afterArrayEqual ); | ||
} ); | ||
|
||
suite.add( name + ' (array, same)', () => { | ||
isShallowEqualArrays( beforeArray, afterArraySame ); | ||
} ); | ||
|
||
suite.add( name + ' (array, unequal)', () => { | ||
isShallowEqualArrays( beforeArray, afterArrayUnequal ); | ||
} ); | ||
} ); | ||
|
||
suite | ||
.on( 'cycle', ( event ) => console.log( event.target.toString() ) ) | ||
.run( { async: true } ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
var isArray = Array.isArray, | ||
keys = Object.keys; | ||
|
||
/** | ||
* Returns true if the two objects are shallow equal, or false otherwise. | ||
* | ||
* @param {Object} a First object to compare. | ||
* @param {Object} b Second object to compare. | ||
* | ||
* @return {Boolean} Whether the two objects are shallow equal. | ||
*/ | ||
function isShallowEqualObjects( a, b ) { | ||
var aKeys, bKeys, i, key; | ||
|
||
if ( a === b ) { | ||
return true; | ||
} | ||
|
||
aKeys = keys( a ); | ||
bKeys = keys( b ); | ||
|
||
if ( aKeys.length !== bKeys.length ) { | ||
return false; | ||
} | ||
|
||
i = 0; | ||
|
||
while ( i < aKeys.length ) { | ||
key = aKeys[ i ]; | ||
if ( a[ key ] !== b[ key ] ) { | ||
return false; | ||
} | ||
|
||
i++; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Returns true if the two arrays are shallow equal, or false otherwise. | ||
* | ||
* @param {Array} a First array to compare. | ||
* @param {Array} b Second array to compare. | ||
* | ||
* @return {Boolean} Whether the two arrays are shallow equal. | ||
*/ | ||
function isShallowEqualArrays( a, b ) { | ||
var i; | ||
|
||
if ( a === b ) { | ||
return true; | ||
} | ||
|
||
if ( a.length !== b.length ) { | ||
return false; | ||
} | ||
|
||
for ( i = 0; i < a.length; i++ ) { | ||
if ( a[ i ] !== b[ i ] ) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Returns true if the two arrays or objects are shallow equal, or false | ||
* otherwise. | ||
* | ||
* @param {(Array|Object)} a First object or array to compare. | ||
* @param {(Array|Object)} b Second object or array to compare. | ||
* | ||
* @return {Boolean} Whether the two values are shallow equal. | ||
*/ | ||
function isShallowEqual( a, b ) { | ||
var aIsArray = isArray( a ), | ||
bIsArray = isArray( b ); | ||
|
||
if ( aIsArray !== bIsArray ) { | ||
return false; | ||
} | ||
|
||
if ( aIsArray ) { | ||
return isShallowEqualArrays( a, b ); | ||
} | ||
|
||
return isShallowEqualObjects( a, b ); | ||
} | ||
|
||
module.exports = isShallowEqual; | ||
module.exports.isShallowEqualObjects = isShallowEqualObjects; | ||
module.exports.isShallowEqualArrays = isShallowEqualArrays; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require( './' ).isShallowEqualObjects; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "@wordpress/is-shallow-equal", | ||
"version": "1.0.0", | ||
"description": "Test for shallow equality between two objects or arrays", | ||
"author": "WordPress", | ||
"license": "GPL-2.0-or-later", | ||
"keywords": [ | ||
"shallow", | ||
"shallow-equal", | ||
"shallowequal" | ||
], | ||
"homepage": "https://github.com/WordPress/packages/tree/master/packages/is-shallow-equal/README.md", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/WordPress/packages.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/WordPress/packages/issues" | ||
}, | ||
"main": "build/index.js", | ||
"module": "build-module/index.js", | ||
"devDependencies": { | ||
"benchmark": "^2.1.4", | ||
"fbjs": "^0.8.16", | ||
"is-equal-shallow": "^0.1.3", | ||
"shallow-equal": "^1.0.0", | ||
"shallow-equals": "^1.0.0", | ||
"shallowequal": "^1.0.2" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
Oops, something went wrong.