| 'use strict'; |
| |
| var keysShim; |
| if (!Object.keys) { |
| // modified from https://github.com/es-shims/es5-shim |
| var has = Object.prototype.hasOwnProperty; |
| var toStr = Object.prototype.toString; |
| var isArgs = require('./isArguments'); // eslint-disable-line global-require |
| var isEnumerable = Object.prototype.propertyIsEnumerable; |
| var hasDontEnumBug = !isEnumerable.call({ toString: null }, 'toString'); |
| var hasProtoEnumBug = isEnumerable.call(function () {}, 'prototype'); |
| var dontEnums = [ |
| 'toString', |
| 'toLocaleString', |
| 'valueOf', |
| 'hasOwnProperty', |
| 'isPrototypeOf', |
| 'propertyIsEnumerable', |
| 'constructor' |
| ]; |
| var equalsConstructorPrototype = function (o) { |
| var ctor = o.constructor; |
| return ctor && ctor.prototype === o; |
| }; |
| var excludedKeys = { |
| $applicationCache: true, |
| $console: true, |
| $external: true, |
| $frame: true, |
| $frameElement: true, |
| $frames: true, |
| $innerHeight: true, |
| $innerWidth: true, |
| $onmozfullscreenchange: true, |
| $onmozfullscreenerror: true, |
| $outerHeight: true, |
| $outerWidth: true, |
| $pageXOffset: true, |
| $pageYOffset: true, |
| $parent: true, |
| $scrollLeft: true, |
| $scrollTop: true, |
| $scrollX: true, |
| $scrollY: true, |
| $self: true, |
| $webkitIndexedDB: true, |
| $webkitStorageInfo: true, |
| $window: true |
| }; |
| var hasAutomationEqualityBug = (function () { |
| /* global window */ |
| if (typeof window === 'undefined') { return false; } |
| for (var k in window) { |
| try { |
| if (!excludedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') { |
| try { |
| equalsConstructorPrototype(window[k]); |
| } catch (e) { |
| return true; |
| } |
| } |
| } catch (e) { |
| return true; |
| } |
| } |
| return false; |
| }()); |
| var equalsConstructorPrototypeIfNotBuggy = function (o) { |
| /* global window */ |
| if (typeof window === 'undefined' || !hasAutomationEqualityBug) { |
| return equalsConstructorPrototype(o); |
| } |
| try { |
| return equalsConstructorPrototype(o); |
| } catch (e) { |
| return false; |
| } |
| }; |
| |
| keysShim = function keys(object) { |
| var isObject = object !== null && typeof object === 'object'; |
| var isFunction = toStr.call(object) === '[object Function]'; |
| var isArguments = isArgs(object); |
| var isString = isObject && toStr.call(object) === '[object String]'; |
| var theKeys = []; |
| |
| if (!isObject && !isFunction && !isArguments) { |
| throw new TypeError('Object.keys called on a non-object'); |
| } |
| |
| var skipProto = hasProtoEnumBug && isFunction; |
| if (isString && object.length > 0 && !has.call(object, 0)) { |
| for (var i = 0; i < object.length; ++i) { |
| theKeys.push(String(i)); |
| } |
| } |
| |
| if (isArguments && object.length > 0) { |
| for (var j = 0; j < object.length; ++j) { |
| theKeys.push(String(j)); |
| } |
| } else { |
| for (var name in object) { |
| if (!(skipProto && name === 'prototype') && has.call(object, name)) { |
| theKeys.push(String(name)); |
| } |
| } |
| } |
| |
| if (hasDontEnumBug) { |
| var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object); |
| |
| for (var k = 0; k < dontEnums.length; ++k) { |
| if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) { |
| theKeys.push(dontEnums[k]); |
| } |
| } |
| } |
| return theKeys; |
| }; |
| } |
| module.exports = keysShim; |