underscore-rails 1.7.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5576b859213b27f6b5e4d9dda4cf59e7be14d389
4
- data.tar.gz: 773709d74cc092353d7ef8ba8ac1e292e3136cce
3
+ metadata.gz: ce8085a066bdc1f92a0f5acb443d499285a8e00f
4
+ data.tar.gz: 0d019d9874583f7394925d972d1e1c7da5397af8
5
5
  SHA512:
6
- metadata.gz: 19b35afc5770a487bcb3ee1ae373df73d76b4167c2178248681df3a07efb7a86c6ae0c6b36f1fadb951343254a36f3e208fb8165b8c41da224025ed1d93215b6
7
- data.tar.gz: f0bb8b1354a3fabe86a0387098b512f123b1f66aecd2d583cdb15c0b94160777a7c5629fc5dc664b73e4c2f393295e29d914fdde69757fc1a66014f74d122c9a
6
+ metadata.gz: 5982f54fb6ff4e9a100186bfeae138868314c39c29fef3a3e3ce6aaba3c80375fc984d30923119316af15bfde9e1a497adf3a303cc3f4f29d9a9151a922152ad
7
+ data.tar.gz: 32b31f13a3ae31573a74df38c63e143940caadea355102f486d418953a8dff4a0b0afb688e25d07f5851de318ee90bf3beb2c9d38d31551af7a1c874d7bad7f7
@@ -1,5 +1,5 @@
1
1
  module Underscore
2
2
  module Rails
3
- VERSION = "1.7.0"
3
+ VERSION = "1.8.2"
4
4
  end
5
5
  end
@@ -1,6 +1,6 @@
1
- // Underscore.js 1.7.0
1
+ // Underscore.js 1.8.2
2
2
  // http://underscorejs.org
3
- // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
3
+ // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4
4
  // Underscore may be freely distributed under the MIT license.
5
5
 
6
6
  (function() {
@@ -21,7 +21,6 @@
21
21
  var
22
22
  push = ArrayProto.push,
23
23
  slice = ArrayProto.slice,
24
- concat = ArrayProto.concat,
25
24
  toString = ObjProto.toString,
26
25
  hasOwnProperty = ObjProto.hasOwnProperty;
27
26
 
@@ -30,7 +29,11 @@
30
29
  var
31
30
  nativeIsArray = Array.isArray,
32
31
  nativeKeys = Object.keys,
33
- nativeBind = FuncProto.bind;
32
+ nativeBind = FuncProto.bind,
33
+ nativeCreate = Object.create;
34
+
35
+ // Naked function reference for surrogate-prototype-swapping.
36
+ var Ctor = function(){};
34
37
 
35
38
  // Create a safe reference to the Underscore object for use below.
36
39
  var _ = function(obj) {
@@ -52,12 +55,12 @@
52
55
  }
53
56
 
54
57
  // Current version.
55
- _.VERSION = '1.7.0';
58
+ _.VERSION = '1.8.2';
56
59
 
57
60
  // Internal function that returns an efficient (for current engines) version
58
61
  // of the passed-in callback, to be repeatedly applied in other Underscore
59
62
  // functions.
60
- var createCallback = function(func, context, argCount) {
63
+ var optimizeCb = function(func, context, argCount) {
61
64
  if (context === void 0) return func;
62
65
  switch (argCount == null ? 3 : argCount) {
63
66
  case 1: return function(value) {
@@ -81,12 +84,52 @@
81
84
  // A mostly-internal function to generate callbacks that can be applied
82
85
  // to each element in a collection, returning the desired result — either
83
86
  // identity, an arbitrary callback, a property matcher, or a property accessor.
84
- _.iteratee = function(value, context, argCount) {
87
+ var cb = function(value, context, argCount) {
85
88
  if (value == null) return _.identity;
86
- if (_.isFunction(value)) return createCallback(value, context, argCount);
87
- if (_.isObject(value)) return _.matches(value);
89
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
90
+ if (_.isObject(value)) return _.matcher(value);
88
91
  return _.property(value);
89
92
  };
93
+ _.iteratee = function(value, context) {
94
+ return cb(value, context, Infinity);
95
+ };
96
+
97
+ // An internal function for creating assigner functions.
98
+ var createAssigner = function(keysFunc, undefinedOnly) {
99
+ return function(obj) {
100
+ var length = arguments.length;
101
+ if (length < 2 || obj == null) return obj;
102
+ for (var index = 1; index < length; index++) {
103
+ var source = arguments[index],
104
+ keys = keysFunc(source),
105
+ l = keys.length;
106
+ for (var i = 0; i < l; i++) {
107
+ var key = keys[i];
108
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
109
+ }
110
+ }
111
+ return obj;
112
+ };
113
+ };
114
+
115
+ // An internal function for creating a new object that inherits from another.
116
+ var baseCreate = function(prototype) {
117
+ if (!_.isObject(prototype)) return {};
118
+ if (nativeCreate) return nativeCreate(prototype);
119
+ Ctor.prototype = prototype;
120
+ var result = new Ctor;
121
+ Ctor.prototype = null;
122
+ return result;
123
+ };
124
+
125
+ // Helper for collection methods to determine whether a collection
126
+ // should be iterated as an array or as an object
127
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
128
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
129
+ var isArrayLike = function(collection) {
130
+ var length = collection && collection.length;
131
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
132
+ };
90
133
 
91
134
  // Collection Functions
92
135
  // --------------------
@@ -95,11 +138,10 @@
95
138
  // Handles raw objects in addition to array-likes. Treats all
96
139
  // sparse array-likes as if they were dense.
97
140
  _.each = _.forEach = function(obj, iteratee, context) {
98
- if (obj == null) return obj;
99
- iteratee = createCallback(iteratee, context);
100
- var i, length = obj.length;
101
- if (length === +length) {
102
- for (i = 0; i < length; i++) {
141
+ iteratee = optimizeCb(iteratee, context);
142
+ var i, length;
143
+ if (isArrayLike(obj)) {
144
+ for (i = 0, length = obj.length; i < length; i++) {
103
145
  iteratee(obj[i], i, obj);
104
146
  }
105
147
  } else {
@@ -113,77 +155,66 @@
113
155
 
114
156
  // Return the results of applying the iteratee to each element.
115
157
  _.map = _.collect = function(obj, iteratee, context) {
116
- if (obj == null) return [];
117
- iteratee = _.iteratee(iteratee, context);
118
- var keys = obj.length !== +obj.length && _.keys(obj),
158
+ iteratee = cb(iteratee, context);
159
+ var keys = !isArrayLike(obj) && _.keys(obj),
119
160
  length = (keys || obj).length,
120
- results = Array(length),
121
- currentKey;
161
+ results = Array(length);
122
162
  for (var index = 0; index < length; index++) {
123
- currentKey = keys ? keys[index] : index;
163
+ var currentKey = keys ? keys[index] : index;
124
164
  results[index] = iteratee(obj[currentKey], currentKey, obj);
125
165
  }
126
166
  return results;
127
167
  };
128
168
 
129
- var reduceError = 'Reduce of empty array with no initial value';
169
+ // Create a reducing function iterating left or right.
170
+ function createReduce(dir) {
171
+ // Optimized iterator function as using arguments.length
172
+ // in the main function will deoptimize the, see #1991.
173
+ function iterator(obj, iteratee, memo, keys, index, length) {
174
+ for (; index >= 0 && index < length; index += dir) {
175
+ var currentKey = keys ? keys[index] : index;
176
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
177
+ }
178
+ return memo;
179
+ }
180
+
181
+ return function(obj, iteratee, memo, context) {
182
+ iteratee = optimizeCb(iteratee, context, 4);
183
+ var keys = !isArrayLike(obj) && _.keys(obj),
184
+ length = (keys || obj).length,
185
+ index = dir > 0 ? 0 : length - 1;
186
+ // Determine the initial value if none is provided.
187
+ if (arguments.length < 3) {
188
+ memo = obj[keys ? keys[index] : index];
189
+ index += dir;
190
+ }
191
+ return iterator(obj, iteratee, memo, keys, index, length);
192
+ };
193
+ }
130
194
 
131
195
  // **Reduce** builds up a single result from a list of values, aka `inject`,
132
196
  // or `foldl`.
133
- _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
134
- if (obj == null) obj = [];
135
- iteratee = createCallback(iteratee, context, 4);
136
- var keys = obj.length !== +obj.length && _.keys(obj),
137
- length = (keys || obj).length,
138
- index = 0, currentKey;
139
- if (arguments.length < 3) {
140
- if (!length) throw new TypeError(reduceError);
141
- memo = obj[keys ? keys[index++] : index++];
142
- }
143
- for (; index < length; index++) {
144
- currentKey = keys ? keys[index] : index;
145
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
146
- }
147
- return memo;
148
- };
197
+ _.reduce = _.foldl = _.inject = createReduce(1);
149
198
 
150
199
  // The right-associative version of reduce, also known as `foldr`.
151
- _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
152
- if (obj == null) obj = [];
153
- iteratee = createCallback(iteratee, context, 4);
154
- var keys = obj.length !== + obj.length && _.keys(obj),
155
- index = (keys || obj).length,
156
- currentKey;
157
- if (arguments.length < 3) {
158
- if (!index) throw new TypeError(reduceError);
159
- memo = obj[keys ? keys[--index] : --index];
160
- }
161
- while (index--) {
162
- currentKey = keys ? keys[index] : index;
163
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
164
- }
165
- return memo;
166
- };
200
+ _.reduceRight = _.foldr = createReduce(-1);
167
201
 
168
202
  // Return the first value which passes a truth test. Aliased as `detect`.
169
203
  _.find = _.detect = function(obj, predicate, context) {
170
- var result;
171
- predicate = _.iteratee(predicate, context);
172
- _.some(obj, function(value, index, list) {
173
- if (predicate(value, index, list)) {
174
- result = value;
175
- return true;
176
- }
177
- });
178
- return result;
204
+ var key;
205
+ if (isArrayLike(obj)) {
206
+ key = _.findIndex(obj, predicate, context);
207
+ } else {
208
+ key = _.findKey(obj, predicate, context);
209
+ }
210
+ if (key !== void 0 && key !== -1) return obj[key];
179
211
  };
180
212
 
181
213
  // Return all the elements that pass a truth test.
182
214
  // Aliased as `select`.
183
215
  _.filter = _.select = function(obj, predicate, context) {
184
216
  var results = [];
185
- if (obj == null) return results;
186
- predicate = _.iteratee(predicate, context);
217
+ predicate = cb(predicate, context);
187
218
  _.each(obj, function(value, index, list) {
188
219
  if (predicate(value, index, list)) results.push(value);
189
220
  });
@@ -192,19 +223,17 @@
192
223
 
193
224
  // Return all the elements for which a truth test fails.
194
225
  _.reject = function(obj, predicate, context) {
195
- return _.filter(obj, _.negate(_.iteratee(predicate)), context);
226
+ return _.filter(obj, _.negate(cb(predicate)), context);
196
227
  };
197
228
 
198
229
  // Determine whether all of the elements match a truth test.
199
230
  // Aliased as `all`.
200
231
  _.every = _.all = function(obj, predicate, context) {
201
- if (obj == null) return true;
202
- predicate = _.iteratee(predicate, context);
203
- var keys = obj.length !== +obj.length && _.keys(obj),
204
- length = (keys || obj).length,
205
- index, currentKey;
206
- for (index = 0; index < length; index++) {
207
- currentKey = keys ? keys[index] : index;
232
+ predicate = cb(predicate, context);
233
+ var keys = !isArrayLike(obj) && _.keys(obj),
234
+ length = (keys || obj).length;
235
+ for (var index = 0; index < length; index++) {
236
+ var currentKey = keys ? keys[index] : index;
208
237
  if (!predicate(obj[currentKey], currentKey, obj)) return false;
209
238
  }
210
239
  return true;
@@ -213,24 +242,21 @@
213
242
  // Determine if at least one element in the object matches a truth test.
214
243
  // Aliased as `any`.
215
244
  _.some = _.any = function(obj, predicate, context) {
216
- if (obj == null) return false;
217
- predicate = _.iteratee(predicate, context);
218
- var keys = obj.length !== +obj.length && _.keys(obj),
219
- length = (keys || obj).length,
220
- index, currentKey;
221
- for (index = 0; index < length; index++) {
222
- currentKey = keys ? keys[index] : index;
245
+ predicate = cb(predicate, context);
246
+ var keys = !isArrayLike(obj) && _.keys(obj),
247
+ length = (keys || obj).length;
248
+ for (var index = 0; index < length; index++) {
249
+ var currentKey = keys ? keys[index] : index;
223
250
  if (predicate(obj[currentKey], currentKey, obj)) return true;
224
251
  }
225
252
  return false;
226
253
  };
227
254
 
228
255
  // Determine if the array or object contains a given value (using `===`).
229
- // Aliased as `include`.
230
- _.contains = _.include = function(obj, target) {
231
- if (obj == null) return false;
232
- if (obj.length !== +obj.length) obj = _.values(obj);
233
- return _.indexOf(obj, target) >= 0;
256
+ // Aliased as `includes` and `include`.
257
+ _.contains = _.includes = _.include = function(obj, target, fromIndex) {
258
+ if (!isArrayLike(obj)) obj = _.values(obj);
259
+ return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
234
260
  };
235
261
 
236
262
  // Invoke a method (with arguments) on every item in a collection.
@@ -238,7 +264,8 @@
238
264
  var args = slice.call(arguments, 2);
239
265
  var isFunc = _.isFunction(method);
240
266
  return _.map(obj, function(value) {
241
- return (isFunc ? method : value[method]).apply(value, args);
267
+ var func = isFunc ? method : value[method];
268
+ return func == null ? func : func.apply(value, args);
242
269
  });
243
270
  };
244
271
 
@@ -250,13 +277,13 @@
250
277
  // Convenience version of a common use case of `filter`: selecting only objects
251
278
  // containing specific `key:value` pairs.
252
279
  _.where = function(obj, attrs) {
253
- return _.filter(obj, _.matches(attrs));
280
+ return _.filter(obj, _.matcher(attrs));
254
281
  };
255
282
 
256
283
  // Convenience version of a common use case of `find`: getting the first object
257
284
  // containing specific `key:value` pairs.
258
285
  _.findWhere = function(obj, attrs) {
259
- return _.find(obj, _.matches(attrs));
286
+ return _.find(obj, _.matcher(attrs));
260
287
  };
261
288
 
262
289
  // Return the maximum element (or element-based computation).
@@ -264,7 +291,7 @@
264
291
  var result = -Infinity, lastComputed = -Infinity,
265
292
  value, computed;
266
293
  if (iteratee == null && obj != null) {
267
- obj = obj.length === +obj.length ? obj : _.values(obj);
294
+ obj = isArrayLike(obj) ? obj : _.values(obj);
268
295
  for (var i = 0, length = obj.length; i < length; i++) {
269
296
  value = obj[i];
270
297
  if (value > result) {
@@ -272,7 +299,7 @@
272
299
  }
273
300
  }
274
301
  } else {
275
- iteratee = _.iteratee(iteratee, context);
302
+ iteratee = cb(iteratee, context);
276
303
  _.each(obj, function(value, index, list) {
277
304
  computed = iteratee(value, index, list);
278
305
  if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
@@ -289,7 +316,7 @@
289
316
  var result = Infinity, lastComputed = Infinity,
290
317
  value, computed;
291
318
  if (iteratee == null && obj != null) {
292
- obj = obj.length === +obj.length ? obj : _.values(obj);
319
+ obj = isArrayLike(obj) ? obj : _.values(obj);
293
320
  for (var i = 0, length = obj.length; i < length; i++) {
294
321
  value = obj[i];
295
322
  if (value < result) {
@@ -297,7 +324,7 @@
297
324
  }
298
325
  }
299
326
  } else {
300
- iteratee = _.iteratee(iteratee, context);
327
+ iteratee = cb(iteratee, context);
301
328
  _.each(obj, function(value, index, list) {
302
329
  computed = iteratee(value, index, list);
303
330
  if (computed < lastComputed || computed === Infinity && result === Infinity) {
@@ -312,7 +339,7 @@
312
339
  // Shuffle a collection, using the modern version of the
313
340
  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
314
341
  _.shuffle = function(obj) {
315
- var set = obj && obj.length === +obj.length ? obj : _.values(obj);
342
+ var set = isArrayLike(obj) ? obj : _.values(obj);
316
343
  var length = set.length;
317
344
  var shuffled = Array(length);
318
345
  for (var index = 0, rand; index < length; index++) {
@@ -328,7 +355,7 @@
328
355
  // The internal `guard` argument allows it to work with `map`.
329
356
  _.sample = function(obj, n, guard) {
330
357
  if (n == null || guard) {
331
- if (obj.length !== +obj.length) obj = _.values(obj);
358
+ if (!isArrayLike(obj)) obj = _.values(obj);
332
359
  return obj[_.random(obj.length - 1)];
333
360
  }
334
361
  return _.shuffle(obj).slice(0, Math.max(0, n));
@@ -336,7 +363,7 @@
336
363
 
337
364
  // Sort the object's values by a criterion produced by an iteratee.
338
365
  _.sortBy = function(obj, iteratee, context) {
339
- iteratee = _.iteratee(iteratee, context);
366
+ iteratee = cb(iteratee, context);
340
367
  return _.pluck(_.map(obj, function(value, index, list) {
341
368
  return {
342
369
  value: value,
@@ -358,7 +385,7 @@
358
385
  var group = function(behavior) {
359
386
  return function(obj, iteratee, context) {
360
387
  var result = {};
361
- iteratee = _.iteratee(iteratee, context);
388
+ iteratee = cb(iteratee, context);
362
389
  _.each(obj, function(value, index) {
363
390
  var key = iteratee(value, index, obj);
364
391
  behavior(result, value, key);
@@ -386,37 +413,24 @@
386
413
  if (_.has(result, key)) result[key]++; else result[key] = 1;
387
414
  });
388
415
 
389
- // Use a comparator function to figure out the smallest index at which
390
- // an object should be inserted so as to maintain order. Uses binary search.
391
- _.sortedIndex = function(array, obj, iteratee, context) {
392
- iteratee = _.iteratee(iteratee, context, 1);
393
- var value = iteratee(obj);
394
- var low = 0, high = array.length;
395
- while (low < high) {
396
- var mid = low + high >>> 1;
397
- if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
398
- }
399
- return low;
400
- };
401
-
402
416
  // Safely create a real, live array from anything iterable.
403
417
  _.toArray = function(obj) {
404
418
  if (!obj) return [];
405
419
  if (_.isArray(obj)) return slice.call(obj);
406
- if (obj.length === +obj.length) return _.map(obj, _.identity);
420
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
407
421
  return _.values(obj);
408
422
  };
409
423
 
410
424
  // Return the number of elements in an object.
411
425
  _.size = function(obj) {
412
426
  if (obj == null) return 0;
413
- return obj.length === +obj.length ? obj.length : _.keys(obj).length;
427
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
414
428
  };
415
429
 
416
430
  // Split a collection into two arrays: one whose elements all satisfy the given
417
431
  // predicate, and one whose elements all do not satisfy the predicate.
418
432
  _.partition = function(obj, predicate, context) {
419
- predicate = _.iteratee(predicate, context);
433
+ predicate = cb(predicate, context);
420
434
  var pass = [], fail = [];
421
435
  _.each(obj, function(value, key, obj) {
422
436
  (predicate(value, key, obj) ? pass : fail).push(value);
@@ -433,30 +447,27 @@
433
447
  _.first = _.head = _.take = function(array, n, guard) {
434
448
  if (array == null) return void 0;
435
449
  if (n == null || guard) return array[0];
436
- if (n < 0) return [];
437
- return slice.call(array, 0, n);
450
+ return _.initial(array, array.length - n);
438
451
  };
439
452
 
440
453
  // Returns everything but the last entry of the array. Especially useful on
441
454
  // the arguments object. Passing **n** will return all the values in
442
- // the array, excluding the last N. The **guard** check allows it to work with
443
- // `_.map`.
455
+ // the array, excluding the last N.
444
456
  _.initial = function(array, n, guard) {
445
457
  return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
446
458
  };
447
459
 
448
460
  // Get the last element of an array. Passing **n** will return the last N
449
- // values in the array. The **guard** check allows it to work with `_.map`.
461
+ // values in the array.
450
462
  _.last = function(array, n, guard) {
451
463
  if (array == null) return void 0;
452
464
  if (n == null || guard) return array[array.length - 1];
453
- return slice.call(array, Math.max(array.length - n, 0));
465
+ return _.rest(array, Math.max(0, array.length - n));
454
466
  };
455
467
 
456
468
  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
457
469
  // Especially useful on the arguments object. Passing an **n** will return
458
- // the rest N values in the array. The **guard**
459
- // check allows it to work with `_.map`.
470
+ // the rest N values in the array.
460
471
  _.rest = _.tail = _.drop = function(array, n, guard) {
461
472
  return slice.call(array, n == null || guard ? 1 : n);
462
473
  };
@@ -467,18 +478,20 @@
467
478
  };
468
479
 
469
480
  // Internal implementation of a recursive `flatten` function.
470
- var flatten = function(input, shallow, strict, output) {
471
- if (shallow && _.every(input, _.isArray)) {
472
- return concat.apply(output, input);
473
- }
474
- for (var i = 0, length = input.length; i < length; i++) {
481
+ var flatten = function(input, shallow, strict, startIndex) {
482
+ var output = [], idx = 0;
483
+ for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
475
484
  var value = input[i];
476
- if (!_.isArray(value) && !_.isArguments(value)) {
477
- if (!strict) output.push(value);
478
- } else if (shallow) {
479
- push.apply(output, value);
480
- } else {
481
- flatten(value, shallow, strict, output);
485
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
486
+ //flatten current level of array or arguments object
487
+ if (!shallow) value = flatten(value, shallow, strict);
488
+ var j = 0, len = value.length;
489
+ output.length += len;
490
+ while (j < len) {
491
+ output[idx++] = value[j++];
492
+ }
493
+ } else if (!strict) {
494
+ output[idx++] = value;
482
495
  }
483
496
  }
484
497
  return output;
@@ -486,7 +499,7 @@
486
499
 
487
500
  // Flatten out an array, either recursively (by default), or just one level.
488
501
  _.flatten = function(array, shallow) {
489
- return flatten(array, shallow, false, []);
502
+ return flatten(array, shallow, false);
490
503
  };
491
504
 
492
505
  // Return a version of the array that does not contain the specified value(s).
@@ -504,21 +517,21 @@
504
517
  iteratee = isSorted;
505
518
  isSorted = false;
506
519
  }
507
- if (iteratee != null) iteratee = _.iteratee(iteratee, context);
520
+ if (iteratee != null) iteratee = cb(iteratee, context);
508
521
  var result = [];
509
522
  var seen = [];
510
523
  for (var i = 0, length = array.length; i < length; i++) {
511
- var value = array[i];
524
+ var value = array[i],
525
+ computed = iteratee ? iteratee(value, i, array) : value;
512
526
  if (isSorted) {
513
- if (!i || seen !== value) result.push(value);
514
- seen = value;
527
+ if (!i || seen !== computed) result.push(value);
528
+ seen = computed;
515
529
  } else if (iteratee) {
516
- var computed = iteratee(value, i, array);
517
- if (_.indexOf(seen, computed) < 0) {
530
+ if (!_.contains(seen, computed)) {
518
531
  seen.push(computed);
519
532
  result.push(value);
520
533
  }
521
- } else if (_.indexOf(result, value) < 0) {
534
+ } else if (!_.contains(result, value)) {
522
535
  result.push(value);
523
536
  }
524
537
  }
@@ -528,7 +541,7 @@
528
541
  // Produce an array that contains the union: each distinct element from all of
529
542
  // the passed-in arrays.
530
543
  _.union = function() {
531
- return _.uniq(flatten(arguments, true, true, []));
544
+ return _.uniq(flatten(arguments, true, true));
532
545
  };
533
546
 
534
547
  // Produce an array that contains every item shared between all the
@@ -551,7 +564,7 @@
551
564
  // Take the difference between one array and a number of other arrays.
552
565
  // Only the elements present in just the first array will remain.
553
566
  _.difference = function(array) {
554
- var rest = flatten(slice.call(arguments, 1), true, true, []);
567
+ var rest = flatten(arguments, true, true, 1);
555
568
  return _.filter(array, function(value){
556
569
  return !_.contains(rest, value);
557
570
  });
@@ -559,23 +572,28 @@
559
572
 
560
573
  // Zip together multiple lists into a single array -- elements that share
561
574
  // an index go together.
562
- _.zip = function(array) {
563
- if (array == null) return [];
564
- var length = _.max(arguments, 'length').length;
565
- var results = Array(length);
566
- for (var i = 0; i < length; i++) {
567
- results[i] = _.pluck(arguments, i);
575
+ _.zip = function() {
576
+ return _.unzip(arguments);
577
+ };
578
+
579
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
580
+ // each array's elements on shared indices
581
+ _.unzip = function(array) {
582
+ var length = array && _.max(array, 'length').length || 0;
583
+ var result = Array(length);
584
+
585
+ for (var index = 0; index < length; index++) {
586
+ result[index] = _.pluck(array, index);
568
587
  }
569
- return results;
588
+ return result;
570
589
  };
571
590
 
572
591
  // Converts lists into objects. Pass either a single array of `[key, value]`
573
592
  // pairs, or two parallel arrays of the same length -- one of keys, and one of
574
593
  // the corresponding values.
575
594
  _.object = function(list, values) {
576
- if (list == null) return {};
577
595
  var result = {};
578
- for (var i = 0, length = list.length; i < length; i++) {
596
+ for (var i = 0, length = list && list.length; i < length; i++) {
579
597
  if (values) {
580
598
  result[list[i]] = values[i];
581
599
  } else {
@@ -590,30 +608,63 @@
590
608
  // If the array is large and already in sort order, pass `true`
591
609
  // for **isSorted** to use binary search.
592
610
  _.indexOf = function(array, item, isSorted) {
593
- if (array == null) return -1;
594
- var i = 0, length = array.length;
595
- if (isSorted) {
596
- if (typeof isSorted == 'number') {
597
- i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
598
- } else {
599
- i = _.sortedIndex(array, item);
600
- return array[i] === item ? i : -1;
601
- }
611
+ var i = 0, length = array && array.length;
612
+ if (typeof isSorted == 'number') {
613
+ i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
614
+ } else if (isSorted && length) {
615
+ i = _.sortedIndex(array, item);
616
+ return array[i] === item ? i : -1;
617
+ }
618
+ if (item !== item) {
619
+ return _.findIndex(slice.call(array, i), _.isNaN);
602
620
  }
603
621
  for (; i < length; i++) if (array[i] === item) return i;
604
622
  return -1;
605
623
  };
606
624
 
607
625
  _.lastIndexOf = function(array, item, from) {
608
- if (array == null) return -1;
609
- var idx = array.length;
626
+ var idx = array ? array.length : 0;
610
627
  if (typeof from == 'number') {
611
628
  idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
612
629
  }
630
+ if (item !== item) {
631
+ return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
632
+ }
613
633
  while (--idx >= 0) if (array[idx] === item) return idx;
614
634
  return -1;
615
635
  };
616
636
 
637
+ // Generator function to create the findIndex and findLastIndex functions
638
+ function createIndexFinder(dir) {
639
+ return function(array, predicate, context) {
640
+ predicate = cb(predicate, context);
641
+ var length = array != null && array.length;
642
+ var index = dir > 0 ? 0 : length - 1;
643
+ for (; index >= 0 && index < length; index += dir) {
644
+ if (predicate(array[index], index, array)) return index;
645
+ }
646
+ return -1;
647
+ };
648
+ }
649
+
650
+ // Returns the first index on an array-like that passes a predicate test
651
+ _.findIndex = createIndexFinder(1);
652
+
653
+ _.findLastIndex = createIndexFinder(-1);
654
+
655
+ // Use a comparator function to figure out the smallest index at which
656
+ // an object should be inserted so as to maintain order. Uses binary search.
657
+ _.sortedIndex = function(array, obj, iteratee, context) {
658
+ iteratee = cb(iteratee, context, 1);
659
+ var value = iteratee(obj);
660
+ var low = 0, high = array.length;
661
+ while (low < high) {
662
+ var mid = Math.floor((low + high) / 2);
663
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
664
+ }
665
+ return low;
666
+ };
667
+
617
668
  // Generate an integer Array containing an arithmetic progression. A port of
618
669
  // the native Python `range()` function. See
619
670
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
@@ -637,25 +688,25 @@
637
688
  // Function (ahem) Functions
638
689
  // ------------------
639
690
 
640
- // Reusable constructor function for prototype setting.
641
- var Ctor = function(){};
691
+ // Determines whether to execute a function as a constructor
692
+ // or a normal function with the provided arguments
693
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
694
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
695
+ var self = baseCreate(sourceFunc.prototype);
696
+ var result = sourceFunc.apply(self, args);
697
+ if (_.isObject(result)) return result;
698
+ return self;
699
+ };
642
700
 
643
701
  // Create a function bound to a given object (assigning `this`, and arguments,
644
702
  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
645
703
  // available.
646
704
  _.bind = function(func, context) {
647
- var args, bound;
648
705
  if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
649
706
  if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
650
- args = slice.call(arguments, 2);
651
- bound = function() {
652
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
653
- Ctor.prototype = func.prototype;
654
- var self = new Ctor;
655
- Ctor.prototype = null;
656
- var result = func.apply(self, args.concat(slice.call(arguments)));
657
- if (_.isObject(result)) return result;
658
- return self;
707
+ var args = slice.call(arguments, 2);
708
+ var bound = function() {
709
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
659
710
  };
660
711
  return bound;
661
712
  };
@@ -665,15 +716,16 @@
665
716
  // as a placeholder, allowing any combination of arguments to be pre-filled.
666
717
  _.partial = function(func) {
667
718
  var boundArgs = slice.call(arguments, 1);
668
- return function() {
669
- var position = 0;
670
- var args = boundArgs.slice();
671
- for (var i = 0, length = args.length; i < length; i++) {
672
- if (args[i] === _) args[i] = arguments[position++];
719
+ var bound = function() {
720
+ var position = 0, length = boundArgs.length;
721
+ var args = Array(length);
722
+ for (var i = 0; i < length; i++) {
723
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
673
724
  }
674
725
  while (position < arguments.length) args.push(arguments[position++]);
675
- return func.apply(this, args);
726
+ return executeBound(func, bound, this, this, args);
676
727
  };
728
+ return bound;
677
729
  };
678
730
 
679
731
  // Bind a number of an object's methods to that object. Remaining arguments
@@ -693,7 +745,7 @@
693
745
  _.memoize = function(func, hasher) {
694
746
  var memoize = function(key) {
695
747
  var cache = memoize.cache;
696
- var address = hasher ? hasher.apply(this, arguments) : key;
748
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
697
749
  if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
698
750
  return cache[address];
699
751
  };
@@ -712,9 +764,7 @@
712
764
 
713
765
  // Defers a function, scheduling it to run after the current call stack has
714
766
  // cleared.
715
- _.defer = function(func) {
716
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
717
- };
767
+ _.defer = _.partial(_.delay, _, 1);
718
768
 
719
769
  // Returns a function, that, when invoked, will only be triggered at most once
720
770
  // during a given window of time. Normally, the throttled function will run
@@ -739,8 +789,10 @@
739
789
  context = this;
740
790
  args = arguments;
741
791
  if (remaining <= 0 || remaining > wait) {
742
- clearTimeout(timeout);
743
- timeout = null;
792
+ if (timeout) {
793
+ clearTimeout(timeout);
794
+ timeout = null;
795
+ }
744
796
  previous = now;
745
797
  result = func.apply(context, args);
746
798
  if (!timeout) context = args = null;
@@ -761,7 +813,7 @@
761
813
  var later = function() {
762
814
  var last = _.now() - timestamp;
763
815
 
764
- if (last < wait && last > 0) {
816
+ if (last < wait && last >= 0) {
765
817
  timeout = setTimeout(later, wait - last);
766
818
  } else {
767
819
  timeout = null;
@@ -814,7 +866,7 @@
814
866
  };
815
867
  };
816
868
 
817
- // Returns a function that will only be executed after being called N times.
869
+ // Returns a function that will only be executed on and after the Nth call.
818
870
  _.after = function(times, func) {
819
871
  return function() {
820
872
  if (--times < 1) {
@@ -823,15 +875,14 @@
823
875
  };
824
876
  };
825
877
 
826
- // Returns a function that will only be executed before being called N times.
878
+ // Returns a function that will only be executed up to (but not including) the Nth call.
827
879
  _.before = function(times, func) {
828
880
  var memo;
829
881
  return function() {
830
882
  if (--times > 0) {
831
883
  memo = func.apply(this, arguments);
832
- } else {
833
- func = null;
834
884
  }
885
+ if (times <= 1) func = null;
835
886
  return memo;
836
887
  };
837
888
  };
@@ -843,13 +894,47 @@
843
894
  // Object Functions
844
895
  // ----------------
845
896
 
846
- // Retrieve the names of an object's properties.
897
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
898
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
899
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
900
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
901
+
902
+ function collectNonEnumProps(obj, keys) {
903
+ var nonEnumIdx = nonEnumerableProps.length;
904
+ var constructor = obj.constructor;
905
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
906
+
907
+ // Constructor is a special case.
908
+ var prop = 'constructor';
909
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
910
+
911
+ while (nonEnumIdx--) {
912
+ prop = nonEnumerableProps[nonEnumIdx];
913
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
914
+ keys.push(prop);
915
+ }
916
+ }
917
+ }
918
+
919
+ // Retrieve the names of an object's own properties.
847
920
  // Delegates to **ECMAScript 5**'s native `Object.keys`
848
921
  _.keys = function(obj) {
849
922
  if (!_.isObject(obj)) return [];
850
923
  if (nativeKeys) return nativeKeys(obj);
851
924
  var keys = [];
852
925
  for (var key in obj) if (_.has(obj, key)) keys.push(key);
926
+ // Ahem, IE < 9.
927
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
928
+ return keys;
929
+ };
930
+
931
+ // Retrieve all the property names of an object.
932
+ _.allKeys = function(obj) {
933
+ if (!_.isObject(obj)) return [];
934
+ var keys = [];
935
+ for (var key in obj) keys.push(key);
936
+ // Ahem, IE < 9.
937
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
853
938
  return keys;
854
939
  };
855
940
 
@@ -864,6 +949,21 @@
864
949
  return values;
865
950
  };
866
951
 
952
+ // Returns the results of applying the iteratee to each element of the object
953
+ // In contrast to _.map it returns an object
954
+ _.mapObject = function(obj, iteratee, context) {
955
+ iteratee = cb(iteratee, context);
956
+ var keys = _.keys(obj),
957
+ length = keys.length,
958
+ results = {},
959
+ currentKey;
960
+ for (var index = 0; index < length; index++) {
961
+ currentKey = keys[index];
962
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
963
+ }
964
+ return results;
965
+ };
966
+
867
967
  // Convert an object into a list of `[key, value]` pairs.
868
968
  _.pairs = function(obj) {
869
969
  var keys = _.keys(obj);
@@ -896,37 +996,38 @@
896
996
  };
897
997
 
898
998
  // Extend a given object with all the properties in passed-in object(s).
899
- _.extend = function(obj) {
900
- if (!_.isObject(obj)) return obj;
901
- var source, prop;
902
- for (var i = 1, length = arguments.length; i < length; i++) {
903
- source = arguments[i];
904
- for (prop in source) {
905
- if (hasOwnProperty.call(source, prop)) {
906
- obj[prop] = source[prop];
907
- }
908
- }
999
+ _.extend = createAssigner(_.allKeys);
1000
+
1001
+ // Assigns a given object with all the own properties in the passed-in object(s)
1002
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
1003
+ _.extendOwn = _.assign = createAssigner(_.keys);
1004
+
1005
+ // Returns the first key on an object that passes a predicate test
1006
+ _.findKey = function(obj, predicate, context) {
1007
+ predicate = cb(predicate, context);
1008
+ var keys = _.keys(obj), key;
1009
+ for (var i = 0, length = keys.length; i < length; i++) {
1010
+ key = keys[i];
1011
+ if (predicate(obj[key], key, obj)) return key;
909
1012
  }
910
- return obj;
911
1013
  };
912
1014
 
913
1015
  // Return a copy of the object only containing the whitelisted properties.
914
- _.pick = function(obj, iteratee, context) {
915
- var result = {}, key;
1016
+ _.pick = function(object, oiteratee, context) {
1017
+ var result = {}, obj = object, iteratee, keys;
916
1018
  if (obj == null) return result;
917
- if (_.isFunction(iteratee)) {
918
- iteratee = createCallback(iteratee, context);
919
- for (key in obj) {
920
- var value = obj[key];
921
- if (iteratee(value, key, obj)) result[key] = value;
922
- }
1019
+ if (_.isFunction(oiteratee)) {
1020
+ keys = _.allKeys(obj);
1021
+ iteratee = optimizeCb(oiteratee, context);
923
1022
  } else {
924
- var keys = concat.apply([], slice.call(arguments, 1));
925
- obj = new Object(obj);
926
- for (var i = 0, length = keys.length; i < length; i++) {
927
- key = keys[i];
928
- if (key in obj) result[key] = obj[key];
929
- }
1023
+ keys = flatten(arguments, false, false, 1);
1024
+ iteratee = function(value, key, obj) { return key in obj; };
1025
+ obj = Object(obj);
1026
+ }
1027
+ for (var i = 0, length = keys.length; i < length; i++) {
1028
+ var key = keys[i];
1029
+ var value = obj[key];
1030
+ if (iteratee(value, key, obj)) result[key] = value;
930
1031
  }
931
1032
  return result;
932
1033
  };
@@ -936,7 +1037,7 @@
936
1037
  if (_.isFunction(iteratee)) {
937
1038
  iteratee = _.negate(iteratee);
938
1039
  } else {
939
- var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
1040
+ var keys = _.map(flatten(arguments, false, false, 1), String);
940
1041
  iteratee = function(value, key) {
941
1042
  return !_.contains(keys, key);
942
1043
  };
@@ -945,16 +1046,7 @@
945
1046
  };
946
1047
 
947
1048
  // Fill in a given object with default properties.
948
- _.defaults = function(obj) {
949
- if (!_.isObject(obj)) return obj;
950
- for (var i = 1, length = arguments.length; i < length; i++) {
951
- var source = arguments[i];
952
- for (var prop in source) {
953
- if (obj[prop] === void 0) obj[prop] = source[prop];
954
- }
955
- }
956
- return obj;
957
- };
1049
+ _.defaults = createAssigner(_.allKeys, true);
958
1050
 
959
1051
  // Create a (shallow-cloned) duplicate of an object.
960
1052
  _.clone = function(obj) {
@@ -970,6 +1062,19 @@
970
1062
  return obj;
971
1063
  };
972
1064
 
1065
+ // Returns whether an object has a given set of `key:value` pairs.
1066
+ _.isMatch = function(object, attrs) {
1067
+ var keys = _.keys(attrs), length = keys.length;
1068
+ if (object == null) return !length;
1069
+ var obj = Object(object);
1070
+ for (var i = 0; i < length; i++) {
1071
+ var key = keys[i];
1072
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
1073
+ }
1074
+ return true;
1075
+ };
1076
+
1077
+
973
1078
  // Internal recursive comparison function for `isEqual`.
974
1079
  var eq = function(a, b, aStack, bStack) {
975
1080
  // Identical objects are equal. `0 === -0`, but they aren't identical.
@@ -1004,74 +1109,76 @@
1004
1109
  // of `NaN` are not equivalent.
1005
1110
  return +a === +b;
1006
1111
  }
1007
- if (typeof a != 'object' || typeof b != 'object') return false;
1112
+
1113
+ var areArrays = className === '[object Array]';
1114
+ if (!areArrays) {
1115
+ if (typeof a != 'object' || typeof b != 'object') return false;
1116
+
1117
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
1118
+ // from different frames are.
1119
+ var aCtor = a.constructor, bCtor = b.constructor;
1120
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
1121
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
1122
+ && ('constructor' in a && 'constructor' in b)) {
1123
+ return false;
1124
+ }
1125
+ }
1008
1126
  // Assume equality for cyclic structures. The algorithm for detecting cyclic
1009
1127
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1128
+
1129
+ // Initializing stack of traversed objects.
1130
+ // It's done here since we only need them for objects and arrays comparison.
1131
+ aStack = aStack || [];
1132
+ bStack = bStack || [];
1010
1133
  var length = aStack.length;
1011
1134
  while (length--) {
1012
1135
  // Linear search. Performance is inversely proportional to the number of
1013
1136
  // unique nested structures.
1014
1137
  if (aStack[length] === a) return bStack[length] === b;
1015
1138
  }
1016
- // Objects with different constructors are not equivalent, but `Object`s
1017
- // from different frames are.
1018
- var aCtor = a.constructor, bCtor = b.constructor;
1019
- if (
1020
- aCtor !== bCtor &&
1021
- // Handle Object.create(x) cases
1022
- 'constructor' in a && 'constructor' in b &&
1023
- !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
1024
- _.isFunction(bCtor) && bCtor instanceof bCtor)
1025
- ) {
1026
- return false;
1027
- }
1139
+
1028
1140
  // Add the first object to the stack of traversed objects.
1029
1141
  aStack.push(a);
1030
1142
  bStack.push(b);
1031
- var size, result;
1143
+
1032
1144
  // Recursively compare objects and arrays.
1033
- if (className === '[object Array]') {
1145
+ if (areArrays) {
1034
1146
  // Compare array lengths to determine if a deep comparison is necessary.
1035
- size = a.length;
1036
- result = size === b.length;
1037
- if (result) {
1038
- // Deep compare the contents, ignoring non-numeric properties.
1039
- while (size--) {
1040
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
1041
- }
1147
+ length = a.length;
1148
+ if (length !== b.length) return false;
1149
+ // Deep compare the contents, ignoring non-numeric properties.
1150
+ while (length--) {
1151
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
1042
1152
  }
1043
1153
  } else {
1044
1154
  // Deep compare objects.
1045
1155
  var keys = _.keys(a), key;
1046
- size = keys.length;
1156
+ length = keys.length;
1047
1157
  // Ensure that both objects contain the same number of properties before comparing deep equality.
1048
- result = _.keys(b).length === size;
1049
- if (result) {
1050
- while (size--) {
1051
- // Deep compare each member
1052
- key = keys[size];
1053
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
1054
- }
1158
+ if (_.keys(b).length !== length) return false;
1159
+ while (length--) {
1160
+ // Deep compare each member
1161
+ key = keys[length];
1162
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
1055
1163
  }
1056
1164
  }
1057
1165
  // Remove the first object from the stack of traversed objects.
1058
1166
  aStack.pop();
1059
1167
  bStack.pop();
1060
- return result;
1168
+ return true;
1061
1169
  };
1062
1170
 
1063
1171
  // Perform a deep comparison to check if two objects are equal.
1064
1172
  _.isEqual = function(a, b) {
1065
- return eq(a, b, [], []);
1173
+ return eq(a, b);
1066
1174
  };
1067
1175
 
1068
1176
  // Is a given array, string, or object empty?
1069
1177
  // An "empty" object has no enumerable own-properties.
1070
1178
  _.isEmpty = function(obj) {
1071
1179
  if (obj == null) return true;
1072
- if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
1073
- for (var key in obj) if (_.has(obj, key)) return false;
1074
- return true;
1180
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
1181
+ return _.keys(obj).length === 0;
1075
1182
  };
1076
1183
 
1077
1184
  // Is a given value a DOM element?
@@ -1091,14 +1198,14 @@
1091
1198
  return type === 'function' || type === 'object' && !!obj;
1092
1199
  };
1093
1200
 
1094
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
1095
- _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
1201
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
1202
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
1096
1203
  _['is' + name] = function(obj) {
1097
1204
  return toString.call(obj) === '[object ' + name + ']';
1098
1205
  };
1099
1206
  });
1100
1207
 
1101
- // Define a fallback version of the method in browsers (ahem, IE), where
1208
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
1102
1209
  // there isn't any inspectable "Arguments" type.
1103
1210
  if (!_.isArguments(arguments)) {
1104
1211
  _.isArguments = function(obj) {
@@ -1106,8 +1213,9 @@
1106
1213
  };
1107
1214
  }
1108
1215
 
1109
- // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
1110
- if (typeof /./ !== 'function') {
1216
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
1217
+ // IE 11 (#1621), and in Safari 8 (#1929).
1218
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
1111
1219
  _.isFunction = function(obj) {
1112
1220
  return typeof obj == 'function' || false;
1113
1221
  };
@@ -1170,28 +1278,30 @@
1170
1278
 
1171
1279
  _.property = function(key) {
1172
1280
  return function(obj) {
1281
+ return obj == null ? void 0 : obj[key];
1282
+ };
1283
+ };
1284
+
1285
+ // Generates a function for a given object that returns a given property.
1286
+ _.propertyOf = function(obj) {
1287
+ return obj == null ? function(){} : function(key) {
1173
1288
  return obj[key];
1174
1289
  };
1175
1290
  };
1176
1291
 
1177
- // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
1178
- _.matches = function(attrs) {
1179
- var pairs = _.pairs(attrs), length = pairs.length;
1292
+ // Returns a predicate for checking whether an object has a given set of
1293
+ // `key:value` pairs.
1294
+ _.matcher = _.matches = function(attrs) {
1295
+ attrs = _.extendOwn({}, attrs);
1180
1296
  return function(obj) {
1181
- if (obj == null) return !length;
1182
- obj = new Object(obj);
1183
- for (var i = 0; i < length; i++) {
1184
- var pair = pairs[i], key = pair[0];
1185
- if (pair[1] !== obj[key] || !(key in obj)) return false;
1186
- }
1187
- return true;
1297
+ return _.isMatch(obj, attrs);
1188
1298
  };
1189
1299
  };
1190
1300
 
1191
1301
  // Run a function **n** times.
1192
1302
  _.times = function(n, iteratee, context) {
1193
1303
  var accum = Array(Math.max(0, n));
1194
- iteratee = createCallback(iteratee, context, 1);
1304
+ iteratee = optimizeCb(iteratee, context, 1);
1195
1305
  for (var i = 0; i < n; i++) accum[i] = iteratee(i);
1196
1306
  return accum;
1197
1307
  };
@@ -1240,10 +1350,12 @@
1240
1350
 
1241
1351
  // If the value of the named `property` is a function then invoke it with the
1242
1352
  // `object` as context; otherwise, return it.
1243
- _.result = function(object, property) {
1244
- if (object == null) return void 0;
1245
- var value = object[property];
1246
- return _.isFunction(value) ? object[property]() : value;
1353
+ _.result = function(object, property, fallback) {
1354
+ var value = object == null ? void 0 : object[property];
1355
+ if (value === void 0) {
1356
+ value = fallback;
1357
+ }
1358
+ return _.isFunction(value) ? value.call(object) : value;
1247
1359
  };
1248
1360
 
1249
1361
  // Generate a unique integer id (unique within the entire client session).
@@ -1358,8 +1470,8 @@
1358
1470
  // underscore functions. Wrapped objects may be chained.
1359
1471
 
1360
1472
  // Helper function to continue chaining intermediate results.
1361
- var result = function(obj) {
1362
- return this._chain ? _(obj).chain() : obj;
1473
+ var result = function(instance, obj) {
1474
+ return instance._chain ? _(obj).chain() : obj;
1363
1475
  };
1364
1476
 
1365
1477
  // Add your own custom functions to the Underscore object.
@@ -1369,7 +1481,7 @@
1369
1481
  _.prototype[name] = function() {
1370
1482
  var args = [this._wrapped];
1371
1483
  push.apply(args, arguments);
1372
- return result.call(this, func.apply(_, args));
1484
+ return result(this, func.apply(_, args));
1373
1485
  };
1374
1486
  });
1375
1487
  };
@@ -1384,7 +1496,7 @@
1384
1496
  var obj = this._wrapped;
1385
1497
  method.apply(obj, arguments);
1386
1498
  if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
1387
- return result.call(this, obj);
1499
+ return result(this, obj);
1388
1500
  };
1389
1501
  });
1390
1502
 
@@ -1392,7 +1504,7 @@
1392
1504
  _.each(['concat', 'join', 'slice'], function(name) {
1393
1505
  var method = ArrayProto[name];
1394
1506
  _.prototype[name] = function() {
1395
- return result.call(this, method.apply(this._wrapped, arguments));
1507
+ return result(this, method.apply(this._wrapped, arguments));
1396
1508
  };
1397
1509
  });
1398
1510
 
@@ -1401,6 +1513,14 @@
1401
1513
  return this._wrapped;
1402
1514
  };
1403
1515
 
1516
+ // Provide unwrapping proxy for some methods used in engine operations
1517
+ // such as arithmetic and JSON stringification.
1518
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
1519
+
1520
+ _.prototype.toString = function() {
1521
+ return '' + this._wrapped;
1522
+ };
1523
+
1404
1524
  // AMD registration happens at the end for compatibility with AMD loaders
1405
1525
  // that may not enforce next-turn semantics on modules. Even though general
1406
1526
  // practice for AMD registration is to be anonymous, underscore registers
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: underscore-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robin Wenglewski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-28 00:00:00.000000000 Z
11
+ date: 2015-03-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: