Skip to content

Commit 3101e18

Browse files
committed
Merge pull request #2134 from jridgewell/ios-jit-isArrayLike
Fix iOS JIT Bug, Part 2
2 parents 4c7b7e4 + 086a56d commit 3101e18

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

underscore.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,20 @@
122122
return result;
123123
};
124124

125+
var property = function(key) {
126+
return function(obj) {
127+
return obj == null ? void 0 : obj[key];
128+
};
129+
};
130+
125131
// Helper for collection methods to determine whether a collection
126132
// should be iterated as an array or as an object
127133
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
128134
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
129-
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1, LENGTH = 'length';
135+
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
136+
var getLength = property('length');
130137
var isArrayLike = function(collection) {
131-
var length = collection != null && collection[LENGTH];
138+
var length = getLength(collection);
132139
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
133140
};
134141

@@ -482,7 +489,7 @@
482489
// Internal implementation of a recursive `flatten` function.
483490
var flatten = function(input, shallow, strict, startIndex) {
484491
var output = [], idx = 0;
485-
for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
492+
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
486493
var value = input[i];
487494
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
488495
//flatten current level of array or arguments object
@@ -513,7 +520,6 @@
513520
// been sorted, you have the option of using a faster algorithm.
514521
// Aliased as `unique`.
515522
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
516-
if (array == null) return [];
517523
if (!_.isBoolean(isSorted)) {
518524
context = iteratee;
519525
iteratee = isSorted;
@@ -522,7 +528,7 @@
522528
if (iteratee != null) iteratee = cb(iteratee, context);
523529
var result = [];
524530
var seen = [];
525-
for (var i = 0, length = array.length; i < length; i++) {
531+
for (var i = 0, length = getLength(array); i < length; i++) {
526532
var value = array[i],
527533
computed = iteratee ? iteratee(value, i, array) : value;
528534
if (isSorted) {
@@ -549,10 +555,9 @@
549555
// Produce an array that contains every item shared between all the
550556
// passed-in arrays.
551557
_.intersection = function(array) {
552-
if (array == null) return [];
553558
var result = [];
554559
var argsLength = arguments.length;
555-
for (var i = 0, length = array.length; i < length; i++) {
560+
for (var i = 0, length = getLength(array); i < length; i++) {
556561
var item = array[i];
557562
if (_.contains(result, item)) continue;
558563
for (var j = 1; j < argsLength; j++) {
@@ -581,7 +586,7 @@
581586
// Complement of _.zip. Unzip accepts an array of arrays and groups
582587
// each array's elements on shared indices
583588
_.unzip = function(array) {
584-
var length = array && _.max(array, 'length').length || 0;
589+
var length = array && _.max(array, getLength).length || 0;
585590
var result = Array(length);
586591

587592
for (var index = 0; index < length; index++) {
@@ -595,7 +600,7 @@
595600
// the corresponding values.
596601
_.object = function(list, values) {
597602
var result = {};
598-
for (var i = 0, length = list && list.length; i < length; i++) {
603+
for (var i = 0, length = getLength(list); i < length; i++) {
599604
if (values) {
600605
result[list[i]] = values[i];
601606
} else {
@@ -609,7 +614,7 @@
609614
function createPredicateIndexFinder(dir) {
610615
return function(array, predicate, context) {
611616
predicate = cb(predicate, context);
612-
var length = array != null && array.length;
617+
var length = getLength(array);
613618
var index = dir > 0 ? 0 : length - 1;
614619
for (; index >= 0 && index < length; index += dir) {
615620
if (predicate(array[index], index, array)) return index;
@@ -627,7 +632,7 @@
627632
_.sortedIndex = function(array, obj, iteratee, context) {
628633
iteratee = cb(iteratee, context, 1);
629634
var value = iteratee(obj);
630-
var low = 0, high = array.length;
635+
var low = 0, high = getLength(array);
631636
while (low < high) {
632637
var mid = Math.floor((low + high) / 2);
633638
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
@@ -638,7 +643,7 @@
638643
// Generator function to create the indexOf and lastIndexOf functions
639644
function createIndexFinder(dir, predicateFind, sortedIndex) {
640645
return function(array, item, idx) {
641-
var i = 0, length = array ? array.length : -1;
646+
var i = 0, length = getLength(array);
642647
if (typeof idx == 'number') {
643648
if (dir > 0) {
644649
i = idx >= 0 ? idx : Math.max(idx + length, i);
@@ -1136,7 +1141,7 @@
11361141
}
11371142
// Assume equality for cyclic structures. The algorithm for detecting cyclic
11381143
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1139-
1144+
11401145
// Initializing stack of traversed objects.
11411146
// It's done here since we only need them for objects and arrays comparison.
11421147
aStack = aStack || [];
@@ -1287,11 +1292,7 @@
12871292

12881293
_.noop = function(){};
12891294

1290-
_.property = function(key) {
1291-
return function(obj) {
1292-
return obj == null ? void 0 : obj[key];
1293-
};
1294-
};
1295+
_.property = property;
12951296

12961297
// Generates a function for a given object that returns a given property.
12971298
_.propertyOf = function(obj) {
@@ -1300,7 +1301,7 @@
13001301
};
13011302
};
13021303

1303-
// Returns a predicate for checking whether an object has a given set of
1304+
// Returns a predicate for checking whether an object has a given set of
13041305
// `key:value` pairs.
13051306
_.matcher = _.matches = function(attrs) {
13061307
attrs = _.extendOwn({}, attrs);
@@ -1527,7 +1528,7 @@
15271528
// Provide unwrapping proxy for some methods used in engine operations
15281529
// such as arithmetic and JSON stringification.
15291530
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
1530-
1531+
15311532
_.prototype.toString = function() {
15321533
return '' + this._wrapped;
15331534
};

0 commit comments

Comments
 (0)