mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
3.9 KiB
170 lines
3.9 KiB
import { isArray } from './_internals/isArray.js'
|
|
import { type } from './type.js'
|
|
|
|
export function _lastIndexOf(valueToFind, list){
|
|
if (!isArray(list))
|
|
throw new Error(`Cannot read property 'indexOf' of ${ list }`)
|
|
|
|
const typeOfValue = type(valueToFind)
|
|
if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
|
|
return list.lastIndexOf(valueToFind)
|
|
|
|
const { length } = list
|
|
let index = length
|
|
let foundIndex = -1
|
|
|
|
while (--index > -1 && foundIndex === -1)
|
|
if (equals(list[ index ], valueToFind))
|
|
foundIndex = index
|
|
|
|
return foundIndex
|
|
}
|
|
|
|
export function _indexOf(valueToFind, list){
|
|
if (!isArray(list))
|
|
throw new Error(`Cannot read property 'indexOf' of ${ list }`)
|
|
|
|
const typeOfValue = type(valueToFind)
|
|
if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
|
|
return list.indexOf(valueToFind)
|
|
|
|
let index = -1
|
|
let foundIndex = -1
|
|
const { length } = list
|
|
|
|
while (++index < length && foundIndex === -1)
|
|
if (equals(list[ index ], valueToFind))
|
|
foundIndex = index
|
|
|
|
return foundIndex
|
|
}
|
|
|
|
function _arrayFromIterator(iter){
|
|
const list = []
|
|
let next
|
|
while (!(next = iter.next()).done)
|
|
list.push(next.value)
|
|
|
|
return list
|
|
}
|
|
|
|
function _compareSets(a, b){
|
|
if (a.size !== b.size)
|
|
return false
|
|
|
|
const aList = _arrayFromIterator(a.values())
|
|
const bList = _arrayFromIterator(b.values())
|
|
|
|
const filtered = aList.filter(aInstance => _indexOf(aInstance, bList) === -1)
|
|
|
|
return filtered.length === 0
|
|
}
|
|
|
|
function compareErrors(a, b){
|
|
if (a.message !== b.message) return false
|
|
if (a.toString !== b.toString) return false
|
|
|
|
return a.toString() === b.toString()
|
|
}
|
|
|
|
function parseDate(maybeDate){
|
|
if (!maybeDate.toDateString) return [ false ]
|
|
|
|
return [ true, maybeDate.getTime() ]
|
|
}
|
|
|
|
function parseRegex(maybeRegex){
|
|
if (maybeRegex.constructor !== RegExp) return [ false ]
|
|
|
|
return [ true, maybeRegex.toString() ]
|
|
}
|
|
|
|
export function equals(a, b){
|
|
if (arguments.length === 1) return _b => equals(a, _b)
|
|
|
|
if (Object.is(a, b)) return true
|
|
|
|
const aType = type(a)
|
|
|
|
if (aType !== type(b)) return false
|
|
if (aType === 'Function')
|
|
return a.name === undefined ? false : a.name === b.name
|
|
|
|
if ([ 'NaN', 'Null', 'Undefined' ].includes(aType)) return true
|
|
|
|
if ([ 'BigInt', 'Number' ].includes(aType)){
|
|
if (Object.is(-0, a) !== Object.is(-0, b)) return false
|
|
|
|
return a.toString() === b.toString()
|
|
}
|
|
|
|
if ([ 'Boolean', 'String' ].includes(aType))
|
|
return a.toString() === b.toString()
|
|
|
|
if (aType === 'Array'){
|
|
const aClone = Array.from(a)
|
|
const bClone = Array.from(b)
|
|
|
|
if (aClone.toString() !== bClone.toString())
|
|
return false
|
|
|
|
let loopArrayFlag = true
|
|
aClone.forEach((aCloneInstance, aCloneIndex) => {
|
|
if (loopArrayFlag)
|
|
if (
|
|
aCloneInstance !== bClone[ aCloneIndex ] &&
|
|
!equals(aCloneInstance, bClone[ aCloneIndex ])
|
|
)
|
|
loopArrayFlag = false
|
|
|
|
})
|
|
|
|
return loopArrayFlag
|
|
}
|
|
|
|
const aRegex = parseRegex(a)
|
|
const bRegex = parseRegex(b)
|
|
|
|
if (aRegex[ 0 ])
|
|
return bRegex[ 0 ] ? aRegex[ 1 ] === bRegex[ 1 ] : false
|
|
else if (bRegex[ 0 ]) return false
|
|
|
|
const aDate = parseDate(a)
|
|
const bDate = parseDate(b)
|
|
|
|
if (aDate[ 0 ])
|
|
return bDate[ 0 ] ? aDate[ 1 ] === bDate[ 1 ] : false
|
|
else if (bDate[ 0 ]) return false
|
|
|
|
if (a instanceof Error){
|
|
if (!(b instanceof Error)) return false
|
|
|
|
return compareErrors(a, b)
|
|
}
|
|
|
|
if (aType === 'Set')
|
|
return _compareSets(a, b)
|
|
|
|
if (aType === 'Object'){
|
|
const aKeys = Object.keys(a)
|
|
|
|
if (aKeys.length !== Object.keys(b).length)
|
|
return false
|
|
|
|
let loopObjectFlag = true
|
|
aKeys.forEach(aKeyInstance => {
|
|
if (loopObjectFlag){
|
|
const aValue = a[ aKeyInstance ]
|
|
const bValue = b[ aKeyInstance ]
|
|
|
|
if (aValue !== bValue && !equals(aValue, bValue))
|
|
loopObjectFlag = false
|
|
|
|
}
|
|
})
|
|
|
|
return loopObjectFlag
|
|
}
|
|
|
|
return false
|
|
}
|
|
|