OverviewFilesCommitsIssuesDocsReleasesPeers

autobase-doctor / node_modules / same-object / lib / same-set.js

65 lines · javascript ref:
const same = require('../index.js')
const isPrimitive = require('./is-primitive.js')
const findLooseMatchingPrimitives = require('./find-loose-matching-primitives.js')

module.exports = function sameSet (a, b, opts, memos) {
  if (a.size !== b.size) return false

  const set = new Set()

  for (const aValue of a) {
    if (!isPrimitive(aValue)) {
      // Non-null object (non strict only: a not matching primitive)
      set.add(aValue)
    } else if (!b.has(aValue)) {
      if (opts && opts.strict) return false

      // Discard string, symbol, undefined, and null values
      if (!setMightHaveLoosePrim(a, b, aValue)) return false

      set.add(aValue)
    }
  }

  if (set.size > 0) {
    for (const bValue of b) {
      if (!isPrimitive(bValue)) {
        if (!setHasEqualElement(set, bValue, opts, memos)) {
          return false
        }
        continue
      }

      if (opts && opts.strict) continue

      if (a.has(bValue)) continue

      if (setHasEqualElement(set, bValue, opts, memos)) continue

      return false
    }

    return set.size === 0
  }

  return true
}

function setMightHaveLoosePrim (a, b, primitive) {
  const altValue = findLooseMatchingPrimitives(primitive)
  if (altValue != null) return altValue

  return b.has(altValue) && !a.has(altValue)
}

function setHasEqualElement (set, val1, opts, memos) {
  for (const val2 of set) {
    if (same(val1, val2, opts, memos)) {
      set.delete(val2)
      return true
    }
  }

  return false
}