define(['./_setup', './isFunction', './_has'], function (_setup, isFunction, _has) {
  // Internal helper to create a simple lookup structure.
  // `collectNonEnumProps` used to depend on `_.contains`, but this led to
  // circular imports. `emulatedSet` is a one-off solution that only works for
  // arrays of strings.
  function emulatedSet(keys) {
    var hash = {};

    for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;

    return {
      contains: function (key) {
        return hash[key] === true;
      },
      push: function (key) {
        hash[key] = true;
        return keys.push(key);
      }
    };
  } // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
  // be iterated by `for key in ...` and thus missed. Extends `keys` in place if
  // needed.


  function collectNonEnumProps(obj, keys) {
    keys = emulatedSet(keys);
    var nonEnumIdx = _setup.nonEnumerableProps.length;
    var constructor = obj.constructor;

    var proto = isFunction(constructor) && constructor.prototype || _setup.ObjProto; // Constructor is a special case.


    var prop = 'constructor';
    if (_has(obj, prop) && !keys.contains(prop)) keys.push(prop);

    while (nonEnumIdx--) {
      prop = _setup.nonEnumerableProps[nonEnumIdx];

      if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
        keys.push(prop);
      }
    }
  }

  return collectNonEnumProps;
});