UNPKG

kitchensink

Version:

Dispatch's awesome components and style guide

155 lines (119 loc) 4.69 kB
'use strict' function isArguments (obj) { return Object.prototype.toString.call(obj) === '[object Arguments]' } module.exports = match function match (obj, pattern) { return match_(obj, pattern, [], []) } /* istanbul ignore next */ var log = (/\btmatch\b/.test(process.env.NODE_DEBUG || '')) ? console.error : function () {} function match_ (obj, pattern, ca, cb) { log('TMATCH', typeof obj, pattern) if (obj == pattern) { log('TMATCH same object or simple value, or problem') // if one is object, and the other isn't, then this is bogus if (obj === null || pattern === null) { return true } else if (typeof obj === 'object' && typeof pattern === 'object') { return true } else if (typeof obj === 'object' && typeof pattern !== 'object') { return false } else if (typeof obj !== 'object' && typeof pattern === 'object') { return false } else { return true } } else if (obj === null || pattern === null) { log('TMATCH null test, already failed ==') return false } else if (typeof obj === 'string' && pattern instanceof RegExp) { log('TMATCH string~=regexp test') return pattern.test(obj) } else if (typeof obj === 'string' && typeof pattern === 'string' && pattern) { log('TMATCH string~=string test') return obj.indexOf(pattern) !== -1 } else if (obj instanceof Date && pattern instanceof Date) { log('TMATCH date test') return obj.getTime() === pattern.getTime() } else if (obj instanceof Date && typeof pattern === 'string') { log('TMATCH date~=string test') return obj.getTime() === new Date(pattern).getTime() } else if (isArguments(obj) || isArguments(pattern)) { log('TMATCH arguments test') var slice = Array.prototype.slice return match_(slice.call(obj), slice.call(pattern), ca, cb) } else if (pattern === Buffer) { log('TMATCH Buffer ctor') return Buffer.isBuffer(obj) } else if (pattern === Function) { log('TMATCH Function ctor') return typeof obj === 'function' } else if (pattern === Number) { log('TMATCH Number ctor (finite, not NaN)') return typeof obj === 'number' && obj === obj && isFinite(obj) } else if (pattern !== pattern) { log('TMATCH NaN') return obj !== obj } else if (pattern === String) { log('TMATCH String ctor') return typeof obj === 'string' } else if (pattern === Boolean) { log('TMATCH Boolean ctor') return typeof obj === 'boolean' } else if (pattern === Array) { log('TMATCH Array ctor', pattern, Array.isArray(obj)) return Array.isArray(obj) } else if (typeof pattern === 'function' && typeof obj === 'object') { log('TMATCH object~=function') return obj instanceof pattern } else if (typeof obj !== 'object' || typeof pattern !== 'object') { log('TMATCH obj is not object, pattern is not object, false') return false } else if (obj instanceof RegExp && pattern instanceof RegExp) { log('TMATCH regexp~=regexp test') return obj.source === pattern.source && obj.global === pattern.global && obj.multiline === pattern.multiline && obj.lastIndex === pattern.lastIndex && obj.ignoreCase === pattern.ignoreCase } else if (Buffer.isBuffer(obj) && Buffer.isBuffer(pattern)) { log('TMATCH buffer test') if (obj.equals) { return obj.equals(pattern) } else { if (obj.length !== pattern.length) return false for (var j = 0; j < obj.length; j++) if (obj[j] != pattern[j]) return false return true } } else { // both are objects. interesting case! log('TMATCH object~=object test') var kobj = Object.keys(obj) var kpat = Object.keys(pattern) log(' TMATCH patternkeys=%j objkeys=%j', kpat, kobj) // don't bother with stack acrobatics if there's nothing there if (kobj.length === 0 && kpat.length === 0) return true // if we've seen this exact pattern and object already, then // it means that pattern and obj have matching cyclicalness // however, non-cyclical patterns can match cyclical objects log(' TMATCH check seen objects...') var cal = ca.length while (cal--) if (ca[cal] === obj && cb[cal] === pattern) return true ca.push(obj); cb.push(pattern) log(' TMATCH not seen previously') var key for (var l = kpat.length - 1; l >= 0; l--) { key = kpat[l] log(' TMATCH test obj[%j]', key, obj[key], pattern[key]) if (!match_(obj[key], pattern[key], ca, cb)) return false } ca.pop() cb.pop() log(' TMATCH object pass') return true } /* istanbul ignore next */ throw new Error('impossible to reach this point') }