# All files / utils get.ts

91.18% Statements 62/68
81.82% Branches 45/55
100% Functions 11/11
91.04% Lines 61/67

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    1314x

    4x
    4x
    4x
    4x
    4x
    4x

    4x

    4x
    4x

    12x
    4x
    4x

    4x
    2x

    2x
    2x
    2x

    4x
    4x

    4x

    4x
    4x
    4x
    4x

    4x

    4x

    4x
    2x
    2x

    2x
    6x
    6x

    6x
    1x

    6x

    2x

    4x
    206x
    54x

    152x
    152x

    4x
    198x

    198x
    198x

    152x

    46x

    4x
    198x

    198x

    4x
    198x

    198x
    198x

    198x
    206x

    198x

    4x
    217x
    217x

     import {isSymbol} from './isSymbol'

    const INFINITY = 1 / 0
    const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/
    const reIsPlainProp = /^\w*$/
    const charCodeOfDot = '.'.charCodeAt(0)
    const reEscapeChar = /\\(\\)?/g
    const rePropName = RegExp(
      // Match anything that isn't a dot or bracket.
      '[^.[\\]]+' +
        '|' +
        // Or match property names within brackets.
        '\\[(?:' +
        // Match a non-string expression.
        '([^"\'][^[]*)' +
        '|' +
        // Or match strings (supports escaping characters).
        '(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' +
        ')\\]' +
        '|' +
        // Or match "" as the space between consecutive dots or empty brackets.
        '(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))',
      'g'
    )
    const MAX_MEMOIZE_SIZE = 500

    const memoize = (func, resolver) => {
      Iif (
        typeof func !== 'function' ||
        (resolver != null && typeof resolver !== 'function')
      ) {
        throw new TypeError('Expected a function')
      }
      const memoized = (...args) => {
        const key = resolver ? resolver(...args) : args[0]
        const cache = memoized.cache

        if (cache.has(key)) {
          return cache.get(key)
        }
        const result = func(...args)
        memoized.cache = cache.set(key, result) || cache
        return result
      }
      memoized.cache = new (memoize.Cache || Map)()
      return memoized
    }

    memoize.Cache = Map

    const memoizeCapped = func => {
      const result = memoize(func, key => {
        const {cache} = result
        Iif (cache.size === MAX_MEMOIZE_SIZE) {
          cache.clear()
        }
        return key
      })
      return result
    }

    const stringToPath = memoizeCapped(string => {
      const result = []
      Iif (string.charCodeAt(0) === charCodeOfDot) {
        result.push('')
      }
      string.replace(rePropName, (match, expression, quote, subString) => {
        let key = match
        Iif (quote) {
          key = subString.replace(reEscapeChar, '$1')
        } else if (expression) {
          key = expression.trim()
        }
        result.push(key)
      })
      return result
    })

    const toKey = (value: string): string => {
      if (typeof value === 'string' || isSymbol(value)) {
        return value
      }
      const result = `${value}`
      return result == '0' && 1 / value == -INFINITY ? '-0' : result
    }

    const isKey = (value: any, object: any): boolean => {
      Iif (Array.isArray(value)) {
        return false
      }
      const type = typeof value
      if (
        type === 'number' ||
        type === 'boolean' ||
        value == null ||
        isSymbol(value)
      ) {
        return true
      }

      return (
        reIsPlainProp.test(value) ||
        !reIsDeepProp.test(value) ||
        (object != null && value in Object(object))
      )
    }

    const castPath = (value: any, object: any): Array<string> => {
      Iif (Array.isArray(value)) {
        return value
      }
      return isKey(value, object) ? [value] : stringToPath(value)
    }

    const baseGet = (object: any, path: any) => {
      path = castPath(path, object)

      let index = 0
      const length = path.length

      while (object != null && index < length) {
        object = object[toKey(path[index++])]
      }
      return index && index == length ? object : undefined
    }

    export const get = (object?: any, path?: any, defaultValue?: any) => {
      const result = object == null ? undefined : baseGet(object, path)
      return result === undefined ? defaultValue : result
    }