implementation.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. 'use strict';
  2. var keysShim;
  3. if (!Object.keys) {
  4. // modified from https://github.com/es-shims/es5-shim
  5. var has = Object.prototype.hasOwnProperty;
  6. var toStr = Object.prototype.toString;
  7. var isArgs = require('./isArguments'); // eslint-disable-line global-require
  8. var isEnumerable = Object.prototype.propertyIsEnumerable;
  9. var hasDontEnumBug = !isEnumerable.call({ toString: null }, 'toString');
  10. var hasProtoEnumBug = isEnumerable.call(function () {}, 'prototype');
  11. var dontEnums = [
  12. 'toString',
  13. 'toLocaleString',
  14. 'valueOf',
  15. 'hasOwnProperty',
  16. 'isPrototypeOf',
  17. 'propertyIsEnumerable',
  18. 'constructor'
  19. ];
  20. var equalsConstructorPrototype = function (o) {
  21. var ctor = o.constructor;
  22. return ctor && ctor.prototype === o;
  23. };
  24. var excludedKeys = {
  25. $applicationCache: true,
  26. $console: true,
  27. $external: true,
  28. $frame: true,
  29. $frameElement: true,
  30. $frames: true,
  31. $innerHeight: true,
  32. $innerWidth: true,
  33. $onmozfullscreenchange: true,
  34. $onmozfullscreenerror: true,
  35. $outerHeight: true,
  36. $outerWidth: true,
  37. $pageXOffset: true,
  38. $pageYOffset: true,
  39. $parent: true,
  40. $scrollLeft: true,
  41. $scrollTop: true,
  42. $scrollX: true,
  43. $scrollY: true,
  44. $self: true,
  45. $webkitIndexedDB: true,
  46. $webkitStorageInfo: true,
  47. $window: true
  48. };
  49. var hasAutomationEqualityBug = (function () {
  50. /* global window */
  51. if (typeof window === 'undefined') { return false; }
  52. for (var k in window) {
  53. try {
  54. if (!excludedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
  55. try {
  56. equalsConstructorPrototype(window[k]);
  57. } catch (e) {
  58. return true;
  59. }
  60. }
  61. } catch (e) {
  62. return true;
  63. }
  64. }
  65. return false;
  66. }());
  67. var equalsConstructorPrototypeIfNotBuggy = function (o) {
  68. /* global window */
  69. if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
  70. return equalsConstructorPrototype(o);
  71. }
  72. try {
  73. return equalsConstructorPrototype(o);
  74. } catch (e) {
  75. return false;
  76. }
  77. };
  78. keysShim = function keys(object) {
  79. var isObject = object !== null && typeof object === 'object';
  80. var isFunction = toStr.call(object) === '[object Function]';
  81. var isArguments = isArgs(object);
  82. var isString = isObject && toStr.call(object) === '[object String]';
  83. var theKeys = [];
  84. if (!isObject && !isFunction && !isArguments) {
  85. throw new TypeError('Object.keys called on a non-object');
  86. }
  87. var skipProto = hasProtoEnumBug && isFunction;
  88. if (isString && object.length > 0 && !has.call(object, 0)) {
  89. for (var i = 0; i < object.length; ++i) {
  90. theKeys.push(String(i));
  91. }
  92. }
  93. if (isArguments && object.length > 0) {
  94. for (var j = 0; j < object.length; ++j) {
  95. theKeys.push(String(j));
  96. }
  97. } else {
  98. for (var name in object) {
  99. if (!(skipProto && name === 'prototype') && has.call(object, name)) {
  100. theKeys.push(String(name));
  101. }
  102. }
  103. }
  104. if (hasDontEnumBug) {
  105. var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
  106. for (var k = 0; k < dontEnums.length; ++k) {
  107. if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
  108. theKeys.push(dontEnums[k]);
  109. }
  110. }
  111. }
  112. return theKeys;
  113. };
  114. }
  115. module.exports = keysShim;