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; });