-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove 'iterall' as dependency. 'graphql' becomes zero dependen… (#2364)
We used only couple functions from 'iterall' and it's the only dependency we have at the moment. Having no dependencies significantly simplify ESM builds and Deno support in future Partially resolves: #2277 Bonus: All supported Node versions already natively support Array.from so it should improve perfomance
- Loading branch information
1 parent
c90c9a3
commit bde5e4a
Showing
12 changed files
with
216 additions
and
35 deletions.
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
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
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
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,70 @@ | ||
// @flow strict | ||
|
||
import { expect } from 'chai'; | ||
import { describe, it } from 'mocha'; | ||
|
||
import identityFunc from '../identityFunc'; | ||
import isCollection from '../isCollection'; | ||
|
||
describe('isCollection', () => { | ||
it('should return `true` for collections', () => { | ||
expect(isCollection([])).to.equal(true); | ||
expect(isCollection(new Int8Array(1))).to.equal(true); | ||
|
||
// eslint-disable-next-line no-new-wrappers | ||
expect(isCollection(new String('ABC'))).to.equal(true); | ||
|
||
function getArguments() { | ||
return arguments; | ||
} | ||
expect(isCollection(getArguments())).to.equal(true); | ||
|
||
const arrayLike = { | ||
length: 3, | ||
'0': 'Alpha', | ||
'1': 'Bravo', | ||
'2': 'Charlie', | ||
}; | ||
expect(isCollection(arrayLike)).to.equal(true); | ||
|
||
const iterator = { [Symbol.iterator]: identityFunc }; | ||
expect(isCollection(iterator)).to.equal(true); | ||
|
||
// istanbul ignore next | ||
function* generatorFunc() { | ||
/* do nothing */ | ||
} | ||
expect(isCollection(generatorFunc())).to.equal(true); | ||
}); | ||
|
||
it('should return `false` for non-collections', () => { | ||
expect(isCollection(null)).to.equal(false); | ||
expect(isCollection(undefined)).to.equal(false); | ||
|
||
expect(isCollection('ABC')).to.equal(false); | ||
expect(isCollection('0')).to.equal(false); | ||
expect(isCollection('')).to.equal(false); | ||
|
||
expect(isCollection(1)).to.equal(false); | ||
expect(isCollection(0)).to.equal(false); | ||
expect(isCollection(NaN)).to.equal(false); | ||
// eslint-disable-next-line no-new-wrappers | ||
expect(isCollection(new Number(123))).to.equal(false); | ||
|
||
expect(isCollection(true)).to.equal(false); | ||
expect(isCollection(false)).to.equal(false); | ||
// eslint-disable-next-line no-new-wrappers | ||
expect(isCollection(new Boolean(true))).to.equal(false); | ||
|
||
expect(isCollection({})).to.equal(false); | ||
expect(isCollection({ iterable: true })).to.equal(false); | ||
|
||
const iteratorWithoutSymbol = { next: identityFunc }; | ||
expect(isCollection(iteratorWithoutSymbol)).to.equal(false); | ||
|
||
const iteratorWithInvalidTypedSymbol = { | ||
[Symbol.iterator]: { next: identityFunc }, | ||
}; | ||
expect(isCollection(iteratorWithInvalidTypedSymbol)).to.equal(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,39 @@ | ||
// @flow strict | ||
|
||
import { SYMBOL_ITERATOR } from '../polyfills/symbols'; | ||
|
||
/** | ||
* Returns true if the provided object is an Object (i.e. not a string literal) | ||
* and is either Iterable or Array-like. | ||
* | ||
* This may be used in place of [Array.isArray()][isArray] to determine if an | ||
* object should be iterated-over. It always excludes string literals and | ||
* includes Arrays (regardless of if it is Iterable). It also includes other | ||
* Array-like objects such as NodeList, TypedArray, and Buffer. | ||
* | ||
* @example | ||
* | ||
* isCollection([ 1, 2, 3 ]) // true | ||
* isCollection('ABC') // false | ||
* isCollection({ length: 1, 0: 'Alpha' }) // true | ||
* isCollection({ key: 'value' }) // false | ||
* isCollection(new Map()) // true | ||
* | ||
* @param obj | ||
* An Object value which might implement the Iterable or Array-like protocols. | ||
* @return {boolean} true if Iterable or Array-like Object. | ||
*/ | ||
export default function isCollection(obj: mixed): boolean { | ||
if (obj == null || typeof obj !== 'object') { | ||
return false; | ||
} | ||
|
||
// Is Array like? | ||
const length = obj.length; | ||
if (typeof length === 'number' && length >= 0 && length % 1 === 0) { | ||
return true; | ||
} | ||
|
||
// Is Iterable? | ||
return typeof obj[SYMBOL_ITERATOR] === 'function'; | ||
} |
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,57 @@ | ||
// @flow strict | ||
|
||
import { SYMBOL_ITERATOR } from './symbols'; | ||
|
||
declare function arrayFrom<T: mixed>( | ||
arrayLike: mixed, | ||
mapFn?: (elem: mixed, index: number) => T, | ||
thisArg?: mixed, | ||
): Array<T>; | ||
|
||
/* eslint-disable no-redeclare */ | ||
// $FlowFixMe | ||
const arrayFrom = | ||
Array.from || | ||
function(obj, mapFn, thisArg) { | ||
if (obj == null) { | ||
throw new TypeError( | ||
'Array.from requires an array-like object - not null or undefined', | ||
); | ||
} | ||
|
||
// Is Iterable? | ||
const iteratorMethod = obj[SYMBOL_ITERATOR]; | ||
if (typeof iteratorMethod === 'function') { | ||
const iterator = iteratorMethod.call(obj); | ||
const result = []; | ||
let step; | ||
|
||
for (let i = 0; !(step = iterator.next()).done; ++i) { | ||
result.push(mapFn.call(thisArg, step.value, i)); | ||
// Infinite Iterators could cause forEach to run forever. | ||
// After a very large number of iterations, produce an error. | ||
/* istanbul ignore if */ | ||
if (i > 9999999) { | ||
throw new TypeError('Near-infinite iteration.'); | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
// Is Array like? | ||
const length = obj.length; | ||
if (typeof length === 'number' && length >= 0 && length % 1 === 0) { | ||
const result = []; | ||
|
||
for (let i = 0; i < length; ++i) { | ||
if (Object.prototype.hasOwnProperty.call(obj, i)) { | ||
result.push(mapFn.call(thisArg, obj[i], i)); | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
return []; | ||
}; | ||
|
||
export default arrayFrom; |
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,12 @@ | ||
// @flow strict | ||
|
||
// In ES2015 (or a polyfilled) environment, this will be Symbol.iterator | ||
/* istanbul ignore next (See: https://github.com/graphql/graphql-js/issues/2317) */ | ||
export const SYMBOL_ITERATOR: string = | ||
typeof Symbol === 'function' ? Symbol.iterator : '@@iterator'; | ||
|
||
// In ES2017 (or a polyfilled) environment, this will be Symbol.asyncIterator | ||
/* istanbul ignore next (See: https://github.com/graphql/graphql-js/issues/2317) */ | ||
export const SYMBOL_ASYNC_ITERATOR: string = | ||
// $FlowFixMe Flow doesn't define `Symbol.asyncIterator` yet | ||
typeof Symbol === 'function' ? Symbol.asyncIterator : '@@asyncIterator'; |
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
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
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
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
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