shims.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /* eslint-disable */
  2. /* jscs: disable */
  3. 'use strict';
  4. // pulled specific shims from https://github.com/es-shims/es5-shim
  5. var ArrayPrototype = Array.prototype;
  6. var ObjectPrototype = Object.prototype;
  7. var FunctionPrototype = Function.prototype;
  8. var StringPrototype = String.prototype;
  9. var array_slice = ArrayPrototype.slice;
  10. var _toString = ObjectPrototype.toString;
  11. var isFunction = function (val) {
  12. return ObjectPrototype.toString.call(val) === '[object Function]';
  13. };
  14. var isArray = function isArray(obj) {
  15. return _toString.call(obj) === '[object Array]';
  16. };
  17. var isString = function isString(obj) {
  18. return _toString.call(obj) === '[object String]';
  19. };
  20. var supportsDescriptors = Object.defineProperty && (function () {
  21. try {
  22. Object.defineProperty({}, 'x', {});
  23. return true;
  24. } catch (e) { /* this is ES3 */
  25. return false;
  26. }
  27. }());
  28. // Define configurable, writable and non-enumerable props
  29. // if they don't exist.
  30. var defineProperty;
  31. if (supportsDescriptors) {
  32. defineProperty = function (object, name, method, forceAssign) {
  33. if (!forceAssign && (name in object)) { return; }
  34. Object.defineProperty(object, name, {
  35. configurable: true,
  36. enumerable: false,
  37. writable: true,
  38. value: method
  39. });
  40. };
  41. } else {
  42. defineProperty = function (object, name, method, forceAssign) {
  43. if (!forceAssign && (name in object)) { return; }
  44. object[name] = method;
  45. };
  46. }
  47. var defineProperties = function (object, map, forceAssign) {
  48. for (var name in map) {
  49. if (ObjectPrototype.hasOwnProperty.call(map, name)) {
  50. defineProperty(object, name, map[name], forceAssign);
  51. }
  52. }
  53. };
  54. var toObject = function (o) {
  55. if (o == null) { // this matches both null and undefined
  56. throw new TypeError("can't convert " + o + ' to object');
  57. }
  58. return Object(o);
  59. };
  60. //
  61. // Util
  62. // ======
  63. //
  64. // ES5 9.4
  65. // http://es5.github.com/#x9.4
  66. // http://jsperf.com/to-integer
  67. function toInteger(num) {
  68. var n = +num;
  69. if (n !== n) { // isNaN
  70. n = 0;
  71. } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
  72. n = (n > 0 || -1) * Math.floor(Math.abs(n));
  73. }
  74. return n;
  75. }
  76. function ToUint32(x) {
  77. return x >>> 0;
  78. }
  79. //
  80. // Function
  81. // ========
  82. //
  83. // ES-5 15.3.4.5
  84. // http://es5.github.com/#x15.3.4.5
  85. function Empty() {}
  86. defineProperties(FunctionPrototype, {
  87. bind: function bind(that) { // .length is 1
  88. // 1. Let Target be the this value.
  89. var target = this;
  90. // 2. If IsCallable(Target) is false, throw a TypeError exception.
  91. if (!isFunction(target)) {
  92. throw new TypeError('Function.prototype.bind called on incompatible ' + target);
  93. }
  94. // 3. Let A be a new (possibly empty) internal list of all of the
  95. // argument values provided after thisArg (arg1, arg2 etc), in order.
  96. // XXX slicedArgs will stand in for "A" if used
  97. var args = array_slice.call(arguments, 1); // for normal call
  98. // 4. Let F be a new native ECMAScript object.
  99. // 11. Set the [[Prototype]] internal property of F to the standard
  100. // built-in Function prototype object as specified in 15.3.3.1.
  101. // 12. Set the [[Call]] internal property of F as described in
  102. // 15.3.4.5.1.
  103. // 13. Set the [[Construct]] internal property of F as described in
  104. // 15.3.4.5.2.
  105. // 14. Set the [[HasInstance]] internal property of F as described in
  106. // 15.3.4.5.3.
  107. var binder = function () {
  108. if (this instanceof bound) {
  109. // 15.3.4.5.2 [[Construct]]
  110. // When the [[Construct]] internal method of a function object,
  111. // F that was created using the bind function is called with a
  112. // list of arguments ExtraArgs, the following steps are taken:
  113. // 1. Let target be the value of F's [[TargetFunction]]
  114. // internal property.
  115. // 2. If target has no [[Construct]] internal method, a
  116. // TypeError exception is thrown.
  117. // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
  118. // property.
  119. // 4. Let args be a new list containing the same values as the
  120. // list boundArgs in the same order followed by the same
  121. // values as the list ExtraArgs in the same order.
  122. // 5. Return the result of calling the [[Construct]] internal
  123. // method of target providing args as the arguments.
  124. var result = target.apply(
  125. this,
  126. args.concat(array_slice.call(arguments))
  127. );
  128. if (Object(result) === result) {
  129. return result;
  130. }
  131. return this;
  132. } else {
  133. // 15.3.4.5.1 [[Call]]
  134. // When the [[Call]] internal method of a function object, F,
  135. // which was created using the bind function is called with a
  136. // this value and a list of arguments ExtraArgs, the following
  137. // steps are taken:
  138. // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
  139. // property.
  140. // 2. Let boundThis be the value of F's [[BoundThis]] internal
  141. // property.
  142. // 3. Let target be the value of F's [[TargetFunction]] internal
  143. // property.
  144. // 4. Let args be a new list containing the same values as the
  145. // list boundArgs in the same order followed by the same
  146. // values as the list ExtraArgs in the same order.
  147. // 5. Return the result of calling the [[Call]] internal method
  148. // of target providing boundThis as the this value and
  149. // providing args as the arguments.
  150. // equiv: target.call(this, ...boundArgs, ...args)
  151. return target.apply(
  152. that,
  153. args.concat(array_slice.call(arguments))
  154. );
  155. }
  156. };
  157. // 15. If the [[Class]] internal property of Target is "Function", then
  158. // a. Let L be the length property of Target minus the length of A.
  159. // b. Set the length own property of F to either 0 or L, whichever is
  160. // larger.
  161. // 16. Else set the length own property of F to 0.
  162. var boundLength = Math.max(0, target.length - args.length);
  163. // 17. Set the attributes of the length own property of F to the values
  164. // specified in 15.3.5.1.
  165. var boundArgs = [];
  166. for (var i = 0; i < boundLength; i++) {
  167. boundArgs.push('$' + i);
  168. }
  169. // XXX Build a dynamic function with desired amount of arguments is the only
  170. // way to set the length property of a function.
  171. // In environments where Content Security Policies enabled (Chrome extensions,
  172. // for ex.) all use of eval or Function costructor throws an exception.
  173. // However in all of these environments Function.prototype.bind exists
  174. // and so this code will never be executed.
  175. var bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
  176. if (target.prototype) {
  177. Empty.prototype = target.prototype;
  178. bound.prototype = new Empty();
  179. // Clean up dangling references.
  180. Empty.prototype = null;
  181. }
  182. // TODO
  183. // 18. Set the [[Extensible]] internal property of F to true.
  184. // TODO
  185. // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
  186. // 20. Call the [[DefineOwnProperty]] internal method of F with
  187. // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
  188. // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
  189. // false.
  190. // 21. Call the [[DefineOwnProperty]] internal method of F with
  191. // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
  192. // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
  193. // and false.
  194. // TODO
  195. // NOTE Function objects created using Function.prototype.bind do not
  196. // have a prototype property or the [[Code]], [[FormalParameters]], and
  197. // [[Scope]] internal properties.
  198. // XXX can't delete prototype in pure-js.
  199. // 22. Return F.
  200. return bound;
  201. }
  202. });
  203. //
  204. // Array
  205. // =====
  206. //
  207. // ES5 15.4.3.2
  208. // http://es5.github.com/#x15.4.3.2
  209. // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
  210. defineProperties(Array, { isArray: isArray });
  211. var boxedString = Object('a');
  212. var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
  213. var properlyBoxesContext = function properlyBoxed(method) {
  214. // Check node 0.6.21 bug where third parameter is not boxed
  215. var properlyBoxesNonStrict = true;
  216. var properlyBoxesStrict = true;
  217. if (method) {
  218. method.call('foo', function (_, __, context) {
  219. if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
  220. });
  221. method.call([1], function () {
  222. 'use strict';
  223. properlyBoxesStrict = typeof this === 'string';
  224. }, 'x');
  225. }
  226. return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
  227. };
  228. defineProperties(ArrayPrototype, {
  229. forEach: function forEach(fun /*, thisp*/) {
  230. var object = toObject(this),
  231. self = splitString && isString(this) ? this.split('') : object,
  232. thisp = arguments[1],
  233. i = -1,
  234. length = self.length >>> 0;
  235. // If no callback function or if callback is not a callable function
  236. if (!isFunction(fun)) {
  237. throw new TypeError(); // TODO message
  238. }
  239. while (++i < length) {
  240. if (i in self) {
  241. // Invoke the callback function with call, passing arguments:
  242. // context, property value, property key, thisArg object
  243. // context
  244. fun.call(thisp, self[i], i, object);
  245. }
  246. }
  247. }
  248. }, !properlyBoxesContext(ArrayPrototype.forEach));
  249. // ES5 15.4.4.14
  250. // http://es5.github.com/#x15.4.4.14
  251. // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
  252. var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
  253. defineProperties(ArrayPrototype, {
  254. indexOf: function indexOf(sought /*, fromIndex */ ) {
  255. var self = splitString && isString(this) ? this.split('') : toObject(this),
  256. length = self.length >>> 0;
  257. if (!length) {
  258. return -1;
  259. }
  260. var i = 0;
  261. if (arguments.length > 1) {
  262. i = toInteger(arguments[1]);
  263. }
  264. // handle negative indices
  265. i = i >= 0 ? i : Math.max(0, length + i);
  266. for (; i < length; i++) {
  267. if (i in self && self[i] === sought) {
  268. return i;
  269. }
  270. }
  271. return -1;
  272. }
  273. }, hasFirefox2IndexOfBug);
  274. //
  275. // String
  276. // ======
  277. //
  278. // ES5 15.5.4.14
  279. // http://es5.github.com/#x15.5.4.14
  280. // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
  281. // Many browsers do not split properly with regular expressions or they
  282. // do not perform the split correctly under obscure conditions.
  283. // See http://blog.stevenlevithan.com/archives/cross-browser-split
  284. // I've tested in many browsers and this seems to cover the deviant ones:
  285. // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
  286. // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
  287. // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
  288. // [undefined, "t", undefined, "e", ...]
  289. // ''.split(/.?/) should be [], not [""]
  290. // '.'.split(/()()/) should be ["."], not ["", "", "."]
  291. var string_split = StringPrototype.split;
  292. if (
  293. 'ab'.split(/(?:ab)*/).length !== 2 ||
  294. '.'.split(/(.?)(.?)/).length !== 4 ||
  295. 'tesst'.split(/(s)*/)[1] === 't' ||
  296. 'test'.split(/(?:)/, -1).length !== 4 ||
  297. ''.split(/.?/).length ||
  298. '.'.split(/()()/).length > 1
  299. ) {
  300. (function () {
  301. var compliantExecNpcg = /()??/.exec('')[1] === void 0; // NPCG: nonparticipating capturing group
  302. StringPrototype.split = function (separator, limit) {
  303. var string = this;
  304. if (separator === void 0 && limit === 0) {
  305. return [];
  306. }
  307. // If `separator` is not a regex, use native split
  308. if (_toString.call(separator) !== '[object RegExp]') {
  309. return string_split.call(this, separator, limit);
  310. }
  311. var output = [],
  312. flags = (separator.ignoreCase ? 'i' : '') +
  313. (separator.multiline ? 'm' : '') +
  314. (separator.extended ? 'x' : '') + // Proposed for ES6
  315. (separator.sticky ? 'y' : ''), // Firefox 3+
  316. lastLastIndex = 0,
  317. // Make `global` and avoid `lastIndex` issues by working with a copy
  318. separator2, match, lastIndex, lastLength;
  319. separator = new RegExp(separator.source, flags + 'g');
  320. string += ''; // Type-convert
  321. if (!compliantExecNpcg) {
  322. // Doesn't need flags gy, but they don't hurt
  323. separator2 = new RegExp('^' + separator.source + '$(?!\\s)', flags);
  324. }
  325. /* Values for `limit`, per the spec:
  326. * If undefined: 4294967295 // Math.pow(2, 32) - 1
  327. * If 0, Infinity, or NaN: 0
  328. * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
  329. * If negative number: 4294967296 - Math.floor(Math.abs(limit))
  330. * If other: Type-convert, then use the above rules
  331. */
  332. limit = limit === void 0 ?
  333. -1 >>> 0 : // Math.pow(2, 32) - 1
  334. ToUint32(limit);
  335. while (match = separator.exec(string)) {
  336. // `separator.lastIndex` is not reliable cross-browser
  337. lastIndex = match.index + match[0].length;
  338. if (lastIndex > lastLastIndex) {
  339. output.push(string.slice(lastLastIndex, match.index));
  340. // Fix browsers whose `exec` methods don't consistently return `undefined` for
  341. // nonparticipating capturing groups
  342. if (!compliantExecNpcg && match.length > 1) {
  343. match[0].replace(separator2, function () {
  344. for (var i = 1; i < arguments.length - 2; i++) {
  345. if (arguments[i] === void 0) {
  346. match[i] = void 0;
  347. }
  348. }
  349. });
  350. }
  351. if (match.length > 1 && match.index < string.length) {
  352. ArrayPrototype.push.apply(output, match.slice(1));
  353. }
  354. lastLength = match[0].length;
  355. lastLastIndex = lastIndex;
  356. if (output.length >= limit) {
  357. break;
  358. }
  359. }
  360. if (separator.lastIndex === match.index) {
  361. separator.lastIndex++; // Avoid an infinite loop
  362. }
  363. }
  364. if (lastLastIndex === string.length) {
  365. if (lastLength || !separator.test('')) {
  366. output.push('');
  367. }
  368. } else {
  369. output.push(string.slice(lastLastIndex));
  370. }
  371. return output.length > limit ? output.slice(0, limit) : output;
  372. };
  373. }());
  374. // [bugfix, chrome]
  375. // If separator is undefined, then the result array contains just one String,
  376. // which is the this value (converted to a String). If limit is not undefined,
  377. // then the output array is truncated so that it contains no more than limit
  378. // elements.
  379. // "0".split(undefined, 0) -> []
  380. } else if ('0'.split(void 0, 0).length) {
  381. StringPrototype.split = function split(separator, limit) {
  382. if (separator === void 0 && limit === 0) { return []; }
  383. return string_split.call(this, separator, limit);
  384. };
  385. }
  386. // ECMA-262, 3rd B.2.3
  387. // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
  388. // non-normative section suggesting uniform semantics and it should be
  389. // normalized across all browsers
  390. // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
  391. var string_substr = StringPrototype.substr;
  392. var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
  393. defineProperties(StringPrototype, {
  394. substr: function substr(start, length) {
  395. return string_substr.call(
  396. this,
  397. start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,
  398. length
  399. );
  400. }
  401. }, hasNegativeSubstrBug);