| '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; |