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