diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..eaf18e596
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,17 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+
+[*]
+
+indent_style = space
+indent_size = 2
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[**/package.json]
+indent_size = 2
diff --git a/docs/modules/_flatten.html b/docs/modules/_flatten.html
index 5534fcdee..3aebfdb12 100644
--- a/docs/modules/_flatten.html
+++ b/docs/modules/_flatten.html
@@ -863,21 +863,12 @@
_flatten.js
- Internal implementation of a recursive flatten function.
+ Internal implementation of a flatten function.
- export default function flatten(input, depth, strict, output) {
- output = output || [];
- if (!depth && depth !== 0) {
- depth = Infinity;
- } else if (depth <= 0) {
- return output.concat(input);
- }
- var idx = output.length;
- for (var i = 0, length = getLength(input); i < length; i++) {
- var value = input[i];
- if (isArrayLike(value) && (isArray(value) || isArguments(value))) {
+ export default function flatten(input, depth, strict) {
+ if (!depth && depth !== 0) depth = Infinity;
@@ -888,17 +879,44 @@ _flatten.js
+ We will be avoiding recursive calls because this could be exploited to
+cause a stack overflow (CVE-2026-27601). Instead, we “trampoline” on an
+explicit stack.
+
+
+
+ var output = [], idx = 0, i = 0, length = getLength(input) || 0, stack = [];
+ while (true) {
+ if (i >= length) {
+ if (!stack.length) break;
+ var frame = stack.pop();
+ i = frame.i;
+ input = frame.v;
+ length = getLength(input);
+ continue;
+ }
+ var value = input[i++];
+ if (stack.length >= depth) {
+ output[idx++] = value;
+ } else if (isArrayLike(value) && (isArray(value) || isArguments(value))) {
+
+
+
+
+
+
+
+
Flatten current level of array or arguments object.
- if (depth > 1) {
- flatten(value, depth - 1, strict, output);
- idx = output.length;
- } else {
- var j = 0, len = value.length;
- while (j < len) output[idx++] = value[j++];
- }
+ stack.push({i: i, v: input});
+ i = 0;
+ input = value;
+ length = getLength(input);
} else if (!strict) {
output[idx++] = value;
}
diff --git a/docs/modules/_setup.html b/docs/modules/_setup.html
index 5bcb72eec..235e3d690 100644
--- a/docs/modules/_setup.html
+++ b/docs/modules/_setup.html
@@ -850,7 +850,7 @@ _setup.js
-
export var VERSION = '1.13.7';
+
export var VERSION = '1.13.8';
diff --git a/docs/modules/index.html b/docs/modules/index.html
index a59e6f36b..9f484cfac 100644
--- a/docs/modules/index.html
+++ b/docs/modules/index.html
@@ -865,9 +865,9 @@
Named Exports
-
Underscore.js 1.13.7
+ Underscore.js 1.13.8
https:
-(c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
+(c) 2009-2026 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
Underscore may be freely distributed under the MIT license.
diff --git a/docs/modules/isEqual.html b/docs/modules/isEqual.html
index 5162cf0e6..3896f4c12 100644
--- a/docs/modules/isEqual.html
+++ b/docs/modules/isEqual.html
@@ -884,11 +884,11 @@ isEqual.js
- Internal recursive comparison function for _.isEqual.
+ Perform a deep comparison to check if two objects are equal.
- function eq(a, b, aStack, bStack) {
+ export default function isEqual(a, b) {
@@ -899,12 +899,13 @@ isEqual.js
- Identical objects are equal. 0 === -0, but they aren’t identical.
-See the Harmony egal proposal.
+ Keep track of which pairs of values need to be compared. We will be
+trampolining on this stack instead of using function recursion.
+(CVE-2026-27601)
-
if (a === b) return a !== 0 || 1 / a === 1 / b;
+
var todo = [{a: a, b: b}];
@@ -915,11 +916,11 @@
isEqual.js
-
null or undefined only equal to itself (strict comparison).
+
Initializing stacks of traversed objects for cycle detection.
- if (a == null || b == null) return false;
+ var aStack = [], bStack = [];
@@ -930,11 +931,12 @@ isEqual.js
- NaNs are equivalent, but non-reflexive.
+ Keep traversing pairs until there is nothing left to compare.
- if (a !== a) return b !== b;
+ while (todo.length) {
+ var frame = todo.pop();
@@ -945,14 +947,12 @@ isEqual.js
- Exhaust primitive checks
+ As a special case, a single true on the todo means that we can
+unwind the cycle detection stacks.
- var type = typeof a;
- if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
- return deepEq(a, b, aStack, bStack);
-}
+
@@ -963,11 +963,16 @@ isEqual.js
- Internal recursive comparison function for _.isEqual.
+ Remove the first object from the stack of traversed objects.
- function deepEq(a, b, aStack, bStack) {
+ aStack.pop();
+ bStack.pop();
+ continue;
+ }
+ a = frame.a;
+ b = frame.b;
@@ -978,12 +983,15 @@ isEqual.js
- Unwrap any wrapped objects.
+ Identical objects are equal. 0 === -0, but they aren’t identical.
+See the Harmony egal proposal.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
+ if (a === b) {
+ if (a !== 0 || 1 / a === 1 / b) continue;
+ return false;
+ }
@@ -994,12 +1002,11 @@ isEqual.js
- Compare [[Class]] names.
+ null or undefined only equal to itself (strict comparison).
- var className = toString.call(a);
- if (className !== toString.call(b)) return false;
+ if (a == null || b == null) return false;
@@ -1010,15 +1017,14 @@ isEqual.js
- Work around a bug in IE 10 - Edge 13.
+ NaNs are equivalent, but non-reflexive.
- if (hasDataViewBug && className == '[object Object]' && isDataView(a)) {
- if (!isDataView(b)) return false;
- className = tagDataView;
- }
- switch (className) {
+ if (a !== a) {
+ if (b !== b) continue;
+ return false;
+ }
@@ -1029,11 +1035,12 @@ isEqual.js
- These types are compared by value.
+ Exhaust primitive checks
-
+ var type = typeof a;
+ if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
@@ -1044,11 +1051,12 @@ isEqual.js
- RegExps are coerced to strings for comparison (Note: ‘’ + /a/i === ‘/a/i’)
+ Unwrap any wrapped objects.
-
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
@@ -1059,13 +1067,12 @@ isEqual.js
- Primitives and their corresponding object wrappers are equivalent; thus, "5" is
-equivalent to new String("5").
+ Compare [[Class]] names.
- return '' + a === '' + b;
- case '[object Number]':
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
@@ -1076,12 +1083,15 @@ isEqual.js
- NaNs are equivalent, but non-reflexive.
-Object(NaN) is equivalent to NaN.
+ Work around a bug in IE 10 - Edge 13.
- if (+a !== +a) return +b !== +b;
+ if (hasDataViewBug && className == '[object Object]' && isDataView(a)) {
+ if (!isDataView(b)) return false;
+ className = tagDataView;
+ }
+ switch (className) {
@@ -1092,13 +1102,11 @@ isEqual.js
- An egal comparison is performed for other numeric values.
+ These types are compared by value.
- return +a === 0 ? 1 / +a === 1 / b : +a === +b;
- case '[object Date]':
- case '[object Boolean]':
+
@@ -1109,17 +1117,11 @@ isEqual.js
- Coerce dates and booleans to numeric primitive values. Dates are compared by their
-millisecond representations. Note that invalid dates with millisecond representations
-of NaN are not equivalent.
+ RegExps are coerced to strings for comparison (Note: ‘’ + /a/i === ‘/a/i’)
- return +a === +b;
- case '[object Symbol]':
- return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
- case '[object ArrayBuffer]':
- case tagDataView:
+
@@ -1130,22 +1132,18 @@ isEqual.js
- Coerce to typed array so we can fall through.
+ Primitives and their corresponding object wrappers are equivalent; thus, "5" is
+equivalent to new String("5").
- return deepEq(toBufferView(a), toBufferView(b), aStack, bStack);
- }
-
- var areArrays = className === '[object Array]';
- if (!areArrays && isTypedArray(a)) {
- var byteLength = getByteLength(a);
- if (byteLength !== getByteLength(b)) return false;
- if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true;
- areArrays = true;
- }
- if (!areArrays) {
- if (typeof a != 'object' || typeof b != 'object') return false;
+ if ('' + a === '' + b) continue;
+ return false;
+ case '[object Number]':
+ todo.push({a: +a, b: +b});
+ continue;
+ case '[object Date]':
+ case '[object Boolean]':
@@ -1156,18 +1154,19 @@ isEqual.js
- Objects with different constructors are not equivalent, but Objects or Arrays
-from different frames are.
+ Coerce dates and booleans to numeric primitive values. Dates are compared by their
+millisecond representations. Note that invalid dates with millisecond representations
+of NaN are not equivalent.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
- isFunction(bCtor) && bCtor instanceof bCtor)
- && ('constructor' in a && 'constructor' in b)) {
+ if (+a === +b) continue;
return false;
- }
- }
+ case '[object Symbol]':
+ if (SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b)) continue;
+ return false;
+ case '[object ArrayBuffer]':
+ case tagDataView:
@@ -1178,11 +1177,24 @@ isEqual.js
- Assume equality for cyclic structures. The algorithm for detecting cyclic
-structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.
+ Coerce to typed array so we can fall through.
+ todo.push({a: toBufferView(a), b: toBufferView(b)});
+ continue;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays && isTypedArray(a)) {
+ var byteLength = getByteLength(a);
+ if (byteLength !== getByteLength(b)) return false;
+ if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) continue;
+ areArrays = true;
+ }
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
@@ -1192,15 +1204,18 @@ isEqual.js
- Initializing stack of traversed objects.
-It’s done here since we only need them for objects and arrays comparison.
+ Objects with different constructors are not equivalent, but Objects or Arrays
+from different frames are.
- aStack = aStack || [];
- bStack = bStack || [];
- var length = aStack.length;
- while (length--) {
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
+ isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
@@ -1211,13 +1226,14 @@ isEqual.js
- Linear search. Performance is inversely proportional to the number of
-unique nested structures.
+ Assume equality for cyclic structures. The algorithm for detecting cyclic
+structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.
- if (aStack[length] === a) return bStack[length] === b;
- }
+
+ var length = aStack.length;
+ while (length--) {
@@ -1228,12 +1244,12 @@ isEqual.js
- Add the first object to the stack of traversed objects.
+ Linear search. Performance is inversely proportional to the number of
+unique nested structures.
- aStack.push(a);
- bStack.push(b);
+ if (aStack[length] === a) {
@@ -1244,11 +1260,15 @@ isEqual.js
- Recursively compare objects and arrays.
+ Cycle detected. Break out of the inner loop and continue the outer
+loop. Step 1:
-
+ if (bStack[length] === b) break;
+ return false;
+ }
+ }
@@ -1259,12 +1279,11 @@ isEqual.js
- Compare array lengths to determine if a deep comparison is necessary.
+ Step 2, use length to verify whether we detected a cycle:
- length = a.length;
- if (length !== b.length) return false;
+ if (length >= 0) continue;
@@ -1275,14 +1294,12 @@ isEqual.js
- Deep compare the contents, ignoring non-numeric properties.
+ Add the first object to the stack of traversed objects.
- while (length--) {
- if (!eq(a[length], b[length], aStack, bStack)) return false;
- }
- } else {
+ aStack.push(a);
+ bStack.push(b);
@@ -1293,12 +1310,11 @@ isEqual.js
- Deep compare objects.
+ Remember to remove them again after the recursion below.
- var _keys = keys(a), key;
- length = _keys.length;
+
@@ -1309,12 +1325,11 @@ isEqual.js
- Ensure that both objects contain the same number of properties before comparing deep equality.
+ Recursively compare objects and arrays.
- if (keys(b).length !== length) return false;
- while (length--) {
+
@@ -1325,14 +1340,12 @@ isEqual.js
- Deep compare each member
+ Compare array lengths to determine if a deep comparison is necessary.
- key = _keys[length];
- if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
- }
- }
+ length = a.length;
+ if (length !== b.length) return false;
@@ -1343,14 +1356,14 @@ isEqual.js
- Remove the first object from the stack of traversed objects.
+ Deep compare the contents, ignoring non-numeric properties.
- aStack.pop();
- bStack.pop();
- return true;
-}
+ while (length--) {
+ todo.push({a: a[length], b: b[length]});
+ }
+ } else {
@@ -1361,12 +1374,63 @@ isEqual.js
- Perform a deep comparison to check if two objects are equal.
+ Deep compare objects.
+
+
+
+ var _keys = keys(a), key;
+ length = _keys.length;
+
+
+
+
+
+
+
+
+
Ensure that both objects contain the same number of properties before comparing deep equality.
+
+
+
+ if (keys(b).length !== length) return false;
+ while (length--) {
+
+
+
+
+
+
+
+
+
Deep compare each member
+
+
+
+ key = _keys[length];
+ if (!has(b, key)) return false;
+ todo.push({a: a[key], b: b[key]});
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+
We made it to the end and found no differences.
- export default function isEqual(a, b) {
- return eq(a, b);
+
diff --git a/docs/underscore-esm.html b/docs/underscore-esm.html
index a783b4513..3aa68a14c 100644
--- a/docs/underscore-esm.html
+++ b/docs/underscore-esm.html
@@ -27,9 +27,9 @@ underscore-esm.js
- Underscore.js 1.13.7
+ Underscore.js 1.13.8
https:
-(c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
+(c) 2009-2026 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
Underscore may be freely distributed under the MIT license.
@@ -48,7 +48,7 @@ underscore-esm.js
-
+
@@ -932,11 +932,11 @@
underscore-esm.js
-
Internal recursive comparison function for _.isEqual.
+
Perform a deep comparison to check if two objects are equal.
- function eq(a, b, aStack, bStack) {
+
@@ -947,12 +947,13 @@ underscore-esm.js
- Identical objects are equal. 0 === -0, but they aren’t identical.
-See the Harmony egal proposal.
+ Keep track of which pairs of values need to be compared. We will be
+trampolining on this stack instead of using function recursion.
+(CVE-2026-27601)
- if (a === b) return a !== 0 || 1 / a === 1 / b;
+ var todo = [{a: a, b: b}];
@@ -963,11 +964,11 @@ underscore-esm.js
- null or undefined only equal to itself (strict comparison).
+ Initializing stacks of traversed objects for cycle detection.
- if (a == null || b == null) return false;
+ var aStack = [], bStack = [];
@@ -978,11 +979,12 @@ underscore-esm.js
- NaNs are equivalent, but non-reflexive.
+ Keep traversing pairs until there is nothing left to compare.
- if (a !== a) return b !== b;
+ while (todo.length) {
+ var frame = todo.pop();
@@ -993,14 +995,12 @@ underscore-esm.js
- Exhaust primitive checks
+ As a special case, a single true on the todo means that we can
+unwind the cycle detection stacks.
- var type = typeof a;
- if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
- return deepEq(a, b, aStack, bStack);
-}
+
@@ -1011,11 +1011,16 @@ underscore-esm.js
- Internal recursive comparison function for _.isEqual.
+ Remove the first object from the stack of traversed objects.
- function deepEq(a, b, aStack, bStack) {
+ aStack.pop();
+ bStack.pop();
+ continue;
+ }
+ a = frame.a;
+ b = frame.b;
@@ -1026,12 +1031,15 @@ underscore-esm.js
- Unwrap any wrapped objects.
+ Identical objects are equal. 0 === -0, but they aren’t identical.
+See the Harmony egal proposal.
- if (a instanceof _$1) a = a._wrapped;
- if (b instanceof _$1) b = b._wrapped;
+ if (a === b) {
+ if (a !== 0 || 1 / a === 1 / b) continue;
+ return false;
+ }
@@ -1042,12 +1050,11 @@ underscore-esm.js
- Compare [[Class]] names.
+ null or undefined only equal to itself (strict comparison).
- var className = toString.call(a);
- if (className !== toString.call(b)) return false;
+ if (a == null || b == null) return false;
@@ -1058,15 +1065,14 @@ underscore-esm.js
- Work around a bug in IE 10 - Edge 13.
+ NaNs are equivalent, but non-reflexive.
- if (hasDataViewBug && className == '[object Object]' && isDataView$1(a)) {
- if (!isDataView$1(b)) return false;
- className = tagDataView;
- }
- switch (className) {
+ if (a !== a) {
+ if (b !== b) continue;
+ return false;
+ }
@@ -1077,11 +1083,12 @@ underscore-esm.js
- These types are compared by value.
+ Exhaust primitive checks
-
+ var type = typeof a;
+ if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
@@ -1092,11 +1099,12 @@ underscore-esm.js
- RegExps are coerced to strings for comparison (Note: ‘’ + /a/i === ‘/a/i’)
+ Unwrap any wrapped objects.
-
+ if (a instanceof _$1) a = a._wrapped;
+ if (b instanceof _$1) b = b._wrapped;
@@ -1107,13 +1115,12 @@ underscore-esm.js
- Primitives and their corresponding object wrappers are equivalent; thus, "5" is
-equivalent to new String("5").
+ Compare [[Class]] names.
- return '' + a === '' + b;
- case '[object Number]':
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
@@ -1124,12 +1131,15 @@ underscore-esm.js
- NaNs are equivalent, but non-reflexive.
-Object(NaN) is equivalent to NaN.
+ Work around a bug in IE 10 - Edge 13.
- if (+a !== +a) return +b !== +b;
+ if (hasDataViewBug && className == '[object Object]' && isDataView$1(a)) {
+ if (!isDataView$1(b)) return false;
+ className = tagDataView;
+ }
+ switch (className) {
@@ -1140,13 +1150,11 @@ underscore-esm.js
- An egal comparison is performed for other numeric values.
+ These types are compared by value.
- return +a === 0 ? 1 / +a === 1 / b : +a === +b;
- case '[object Date]':
- case '[object Boolean]':
+
@@ -1157,17 +1165,11 @@ underscore-esm.js
- Coerce dates and booleans to numeric primitive values. Dates are compared by their
-millisecond representations. Note that invalid dates with millisecond representations
-of NaN are not equivalent.
+ RegExps are coerced to strings for comparison (Note: ‘’ + /a/i === ‘/a/i’)
- return +a === +b;
- case '[object Symbol]':
- return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
- case '[object ArrayBuffer]':
- case tagDataView:
+
@@ -1178,22 +1180,18 @@ underscore-esm.js
- Coerce to typed array so we can fall through.
+ Primitives and their corresponding object wrappers are equivalent; thus, "5" is
+equivalent to new String("5").
- return deepEq(toBufferView(a), toBufferView(b), aStack, bStack);
- }
-
- var areArrays = className === '[object Array]';
- if (!areArrays && isTypedArray$1(a)) {
- var byteLength = getByteLength(a);
- if (byteLength !== getByteLength(b)) return false;
- if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true;
- areArrays = true;
- }
- if (!areArrays) {
- if (typeof a != 'object' || typeof b != 'object') return false;
+ if ('' + a === '' + b) continue;
+ return false;
+ case '[object Number]':
+ todo.push({a: +a, b: +b});
+ continue;
+ case '[object Date]':
+ case '[object Boolean]':
@@ -1204,18 +1202,19 @@ underscore-esm.js
- Objects with different constructors are not equivalent, but Objects or Arrays
-from different frames are.
+ Coerce dates and booleans to numeric primitive values. Dates are compared by their
+millisecond representations. Note that invalid dates with millisecond representations
+of NaN are not equivalent.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor &&
- isFunction$1(bCtor) && bCtor instanceof bCtor)
- && ('constructor' in a && 'constructor' in b)) {
+ if (+a === +b) continue;
return false;
- }
- }
+ case '[object Symbol]':
+ if (SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b)) continue;
+ return false;
+ case '[object ArrayBuffer]':
+ case tagDataView:
@@ -1226,11 +1225,24 @@ underscore-esm.js
- Assume equality for cyclic structures. The algorithm for detecting cyclic
-structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.
+ Coerce to typed array so we can fall through.
+ todo.push({a: toBufferView(a), b: toBufferView(b)});
+ continue;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays && isTypedArray$1(a)) {
+ var byteLength = getByteLength(a);
+ if (byteLength !== getByteLength(b)) return false;
+ if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) continue;
+ areArrays = true;
+ }
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
@@ -1240,15 +1252,18 @@ underscore-esm.js
- Initializing stack of traversed objects.
-It’s done here since we only need them for objects and arrays comparison.
+ Objects with different constructors are not equivalent, but Objects or Arrays
+from different frames are.
- aStack = aStack || [];
- bStack = bStack || [];
- var length = aStack.length;
- while (length--) {
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor &&
+ isFunction$1(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
@@ -1259,13 +1274,14 @@ underscore-esm.js
- Linear search. Performance is inversely proportional to the number of
-unique nested structures.
+ Assume equality for cyclic structures. The algorithm for detecting cyclic
+structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.
- if (aStack[length] === a) return bStack[length] === b;
- }
+
+ var length = aStack.length;
+ while (length--) {
@@ -1276,12 +1292,12 @@ underscore-esm.js
- Add the first object to the stack of traversed objects.
+ Linear search. Performance is inversely proportional to the number of
+unique nested structures.
- aStack.push(a);
- bStack.push(b);
+ if (aStack[length] === a) {
@@ -1292,11 +1308,15 @@ underscore-esm.js
- Recursively compare objects and arrays.
+ Cycle detected. Break out of the inner loop and continue the outer
+loop. Step 1:
-
+ if (bStack[length] === b) break;
+ return false;
+ }
+ }
@@ -1307,12 +1327,11 @@ underscore-esm.js
- Compare array lengths to determine if a deep comparison is necessary.
+ Step 2, use length to verify whether we detected a cycle:
- length = a.length;
- if (length !== b.length) return false;
+ if (length >= 0) continue;
@@ -1323,14 +1342,12 @@ underscore-esm.js
- Deep compare the contents, ignoring non-numeric properties.
+ Add the first object to the stack of traversed objects.
- while (length--) {
- if (!eq(a[length], b[length], aStack, bStack)) return false;
- }
- } else {
+ aStack.push(a);
+ bStack.push(b);
@@ -1341,12 +1358,11 @@ underscore-esm.js
- Deep compare objects.
+ Remember to remove them again after the recursion below.
- var _keys = keys(a), key;
- length = _keys.length;
+
@@ -1357,12 +1373,11 @@ underscore-esm.js
- Ensure that both objects contain the same number of properties before comparing deep equality.
+ Recursively compare objects and arrays.
- if (keys(b).length !== length) return false;
- while (length--) {
+
@@ -1373,14 +1388,12 @@ underscore-esm.js
- Deep compare each member
+ Compare array lengths to determine if a deep comparison is necessary.
- key = _keys[length];
- if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
- }
- }
+ length = a.length;
+ if (length !== b.length) return false;
@@ -1391,14 +1404,14 @@ underscore-esm.js
- Remove the first object from the stack of traversed objects.
+ Deep compare the contents, ignoring non-numeric properties.
- aStack.pop();
- bStack.pop();
- return true;
-}
+ while (length--) {
+ todo.push({a: a[length], b: b[length]});
+ }
+ } else {
@@ -1409,13 +1422,12 @@ underscore-esm.js
- Perform a deep comparison to check if two objects are equal.
+ Deep compare objects.
- function isEqual(a, b) {
- return eq(a, b);
-}
+ var _keys = keys(a), key;
+ length = _keys.length;
@@ -1426,6 +1438,58 @@ underscore-esm.js
+ Ensure that both objects contain the same number of properties before comparing deep equality.
+
+
+
+ if (keys(b).length !== length) return false;
+ while (length--) {
+
+
+
+
+
+
+
+
+
Deep compare each member
+
+
+
+ key = _keys[length];
+ if (!has$1(b, key)) return false;
+ todo.push({a: a[key], b: b[key]});
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+
We made it to the end and found no differences.
+
+
+
+
+
+
+
+
+
+
+
+
Retrieve all the enumerable property names of an object.
@@ -1438,11 +1502,11 @@ underscore-esm.js
-
+
Ahem, IE < 9.
@@ -1455,11 +1519,11 @@
underscore-esm.js
-
+
Since the regular Object.prototype.toString type tests don’t work for
some types in IE 11, we use a fingerprinting heuristic instead, based
@@ -1476,11 +1540,11 @@
underscore-esm.js
-
+
Map, WeakMap and Set have no enumerable keys.
@@ -1495,11 +1559,11 @@
underscore-esm.js
-
+
If we are testing against WeakMap, we need to ensure that
obj doesn’t have a forEach method in order to distinguish
@@ -1514,11 +1578,11 @@
underscore-esm.js
-
+
In the interest of compact minification, we write
each string in the fingerprints only once.
@@ -1533,11 +1597,11 @@
underscore-esm.js
-
+
Map, WeakMap and Set each have slightly different
combinations of the above sublists.
@@ -1559,11 +1623,11 @@
underscore-esm.js
-
+
Retrieve the values of an object’s properties.
@@ -1582,11 +1646,11 @@
underscore-esm.js
-
+
Convert an object into a list of [key, value] pairs.
The opposite of _.object with one argument.
@@ -1606,11 +1670,11 @@
underscore-esm.js
-
+
Invert the keys and values of an object. The values must be serializable.
@@ -1628,11 +1692,11 @@
underscore-esm.js
-
+
Return a sorted list of the function names available on the object.
@@ -1649,11 +1713,11 @@
underscore-esm.js
-
+
An internal function for creating assigner functions.
@@ -1680,11 +1744,11 @@
underscore-esm.js
-
+
Extend a given object with all the properties in passed-in object(s).
@@ -1695,11 +1759,11 @@
underscore-esm.js
-
+
Assigns a given object with all the own properties in the passed-in
object(s).
@@ -1712,11 +1776,11 @@
underscore-esm.js
-
+
Fill in a given object with default properties.
@@ -1727,11 +1791,11 @@
underscore-esm.js
-
+
Create a naked function reference for surrogate-prototype-swapping.
@@ -1744,11 +1808,11 @@
underscore-esm.js
-
+
An internal function for creating a new object that inherits from another.
@@ -1767,11 +1831,11 @@
underscore-esm.js
-
+
Creates an object that inherits from the given prototype object.
If additional properties are provided then they will be added to the
@@ -1788,11 +1852,11 @@
underscore-esm.js
-
+
Create a (shallow-cloned) duplicate of an object.
@@ -1806,11 +1870,11 @@
underscore-esm.js
-
+
Invokes interceptor with the obj and then returns obj.
The primary purpose of this method is to “tap into” a method chain, in
@@ -1826,11 +1890,11 @@
underscore-esm.js
-
+
Normalize a (deep) property path to array.
Like _.iteratee, this function can be customized.
@@ -1845,11 +1909,11 @@
underscore-esm.js
-
+
Internal wrapper for _.toPath to enable minification.
Similar to cb for _.iteratee.
@@ -1863,11 +1927,11 @@
underscore-esm.js
-
+
Internal function to obtain a nested property in obj along path.
@@ -1885,11 +1949,11 @@
underscore-esm.js
-
+
Get the value of the (deep) property on path from object.
If any property in path does not exist or if the value is
@@ -1906,11 +1970,11 @@
underscore-esm.js
-
+
Shortcut function for checking if an object has a given property directly on
itself (in other words, not on a prototype). Unlike the internal has
@@ -1932,11 +1996,11 @@
underscore-esm.js
-
+
Keep the identity function around for default iteratees.
@@ -1949,11 +2013,11 @@
underscore-esm.js
-
+
Returns a predicate for checking whether an object has a given set of
key:value pairs.
@@ -1970,11 +2034,11 @@
underscore-esm.js
-
+
Creates a function that, when passed an object, will traverse that object’s
properties down the given path, specified as an array of keys or indices.
@@ -1991,11 +2055,11 @@
underscore-esm.js
-
+
Internal function that returns an efficient (for current engines) version
of the passed-in callback, to be repeatedly applied in other Underscore
@@ -2013,11 +2077,11 @@
underscore-esm.js
-
+
The 2-argument case is omitted because we’re not using it.
@@ -2038,11 +2102,11 @@
underscore-esm.js
-
+
An internal function to generate callbacks that can be applied to each
element in a collection, returning the desired result — either _.identity,
@@ -2060,11 +2124,11 @@
underscore-esm.js
-
+
External wrapper for our callback generator. Users may customize
_.iteratee if they want additional predicate/iteratee shorthand styles.
@@ -2080,11 +2144,11 @@
underscore-esm.js
-
+
The function we call internally to generate a callback. It invokes
_.iteratee if overridden, otherwise baseIteratee.
@@ -2099,11 +2163,11 @@
underscore-esm.js
-
+
Returns the results of applying the iteratee to each element of obj.
In contrast to _.map it returns an object.
@@ -2125,11 +2189,11 @@
underscore-esm.js
-
+
Predicate-generating function. Often useful outside of Underscore.
@@ -2140,11 +2204,11 @@
underscore-esm.js
-
+
Generates a function for a given object that returns a given property.
@@ -2160,11 +2224,11 @@
underscore-esm.js
-
+
Run a function n times.
@@ -2180,11 +2244,11 @@
underscore-esm.js
-
+
Return a random integer between min and max (inclusive).
@@ -2201,11 +2265,11 @@
underscore-esm.js
-
+
A (possibly faster) way to get the current timestamp as an integer.
@@ -2218,11 +2282,11 @@
underscore-esm.js
-
+
Internal helper to generate functions for escaping and unescaping strings
to/from HTML interpolation.
@@ -2237,11 +2301,11 @@
underscore-esm.js
-
+
Regexes for identifying a key that needs to be escaped.
@@ -2259,11 +2323,11 @@
underscore-esm.js
-
+
Internal list of HTML entities for escaping.
@@ -2281,11 +2345,11 @@
underscore-esm.js
-
+
Function for escaping strings to HTML interpolation.
@@ -2296,11 +2360,11 @@
underscore-esm.js
-
+
Internal list of HTML entities for unescaping.
@@ -2311,11 +2375,11 @@
underscore-esm.js
-
+
Function for unescaping strings from HTML interpolation.
@@ -2326,11 +2390,11 @@
underscore-esm.js
-
+
By default, Underscore uses ERB-style template delimiters. Change the
following template settings to use alternative delimiters.
@@ -2346,11 +2410,11 @@
underscore-esm.js
-
+
When customizing _.templateSettings, if you don’t want to define an
interpolation, evaluation or escaping regex, we need one that is
@@ -2363,11 +2427,11 @@
underscore-esm.js
-
+
Certain characters need to be escaped so that they can be put into a
string literal.
@@ -2392,11 +2456,11 @@
underscore-esm.js
-
+
In order to prevent third-party code injection through
_.templateSettings.variable, we test it against the following regular
@@ -2411,11 +2475,11 @@
underscore-esm.js
-
+
JavaScript micro-templating, similar to John Resig’s implementation.
Underscore templating handles arbitrary delimiters, preserves whitespace,
@@ -2431,11 +2495,11 @@
underscore-esm.js
-
+
Combine delimiters into one regular expression via alternation.
@@ -2450,11 +2514,11 @@
underscore-esm.js
-
+
Compile the template source, escaping string literals appropriately.
@@ -2477,11 +2541,11 @@
underscore-esm.js
-
+
Adobe VMs need the match returned to produce the correct offset.
@@ -2497,11 +2561,11 @@
underscore-esm.js
-
+
Insure against third-party code injection. (CVE-2021-23358)
@@ -2515,11 +2579,11 @@
underscore-esm.js
-
+
If a variable is not specified, place data values in local scope.
@@ -2548,11 +2612,11 @@
underscore-esm.js
-
+
Provide the compiled source as a convenience for precompilation.
@@ -2566,11 +2630,11 @@
underscore-esm.js
-
+
Traverses the children of obj along path. If a child is a function, it
is invoked with its parent as context. Returns the value of the final
@@ -2598,11 +2662,11 @@
underscore-esm.js
-
+
Generate a unique integer id (unique within the entire client session).
Useful for temporary DOM ids.
@@ -2618,11 +2682,11 @@
underscore-esm.js
-
+
Start chaining a wrapped Underscore object.
@@ -2637,11 +2701,11 @@
underscore-esm.js
-
+
Internal function to execute sourceFunc bound to context with optional
args. Determines whether to execute a function as a constructor or as a
@@ -2660,11 +2724,11 @@
underscore-esm.js
-
+
Partially apply a function by creating a version that has had some of its
arguments pre-filled, without changing its dynamic this context. _ acts
@@ -2692,11 +2756,11 @@
underscore-esm.js
-
+
Create a function bound to a given object (assigning this, and arguments,
optionally).
@@ -2714,11 +2778,11 @@
underscore-esm.js
-
+
Internal helper for collection methods to determine whether a collection
should be iterated as an array or as an object.
@@ -2732,48 +2796,66 @@
underscore-esm.js
-
+
-
Internal implementation of a recursive flatten function.
+
Internal implementation of a flatten function.
- function flatten$1(input, depth, strict, output) {
- output = output || [];
- if (!depth && depth !== 0) {
- depth = Infinity;
- } else if (depth <= 0) {
- return output.concat(input);
- }
- var idx = output.length;
- for (var i = 0, length = getLength(input); i < length; i++) {
- var value = input[i];
- if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) {
+ function flatten$1(input, depth, strict) {
+ if (!depth && depth !== 0) depth = Infinity;
-
+
+
We will be avoiding recursive calls because this could be exploited to
+cause a stack overflow (CVE-2026-27601). Instead, we “trampoline” on an
+explicit stack.
+
+
+
+ var output = [], idx = 0, i = 0, length = getLength(input) || 0, stack = [];
+ while (true) {
+ if (i >= length) {
+ if (!stack.length) break;
+ var frame = stack.pop();
+ i = frame.i;
+ input = frame.v;
+ length = getLength(input);
+ continue;
+ }
+ var value = input[i++];
+ if (stack.length >= depth) {
+ output[idx++] = value;
+ } else if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) {
+
+
+
+
+
+
+
+
Flatten current level of array or arguments object.
- if (depth > 1) {
- flatten$1(value, depth - 1, strict, output);
- idx = output.length;
- } else {
- var j = 0, len = value.length;
- while (j < len) output[idx++] = value[j++];
- }
+ stack.push({i: i, v: input});
+ i = 0;
+ input = value;
+ length = getLength(input);
} else if (!strict) {
output[idx++] = value;
}
@@ -2784,11 +2866,11 @@ underscore-esm.js
-
+
Bind a number of an object’s methods to that object. Remaining arguments
are the method names to be bound. Useful for ensuring that all callbacks
@@ -2810,11 +2892,11 @@
underscore-esm.js
-
+
Memoize an expensive function by storing its results.
@@ -2834,11 +2916,11 @@
underscore-esm.js
-
+
Delays a function for the given number of milliseconds, and then calls
it with the arguments supplied.
@@ -2854,11 +2936,11 @@
underscore-esm.js
-
+
Defers a function, scheduling it to run after the current call stack has
cleared.
@@ -2870,11 +2952,11 @@
underscore-esm.js
-
+
Returns a function, that, when invoked, will only be triggered at most once
during a given window of time. Normally, the throttled function will run
@@ -2928,11 +3010,11 @@
underscore-esm.js
-
+
When a sequence of calls of the returned function ends, the argument
function is triggered. The end of a sequence is defined by the wait
@@ -2955,11 +3037,11 @@
underscore-esm.js
-
+
This check is needed because func can recursively invoke debounced.
@@ -2991,11 +3073,11 @@
underscore-esm.js
-
+
Returns the first function passed as an argument to the second,
allowing you to adjust arguments, run code before and after, and
@@ -3010,11 +3092,11 @@
underscore-esm.js
-
+
Returns a negated version of the passed-in predicate.
@@ -3029,11 +3111,11 @@
underscore-esm.js
-
+
Returns a function that is the composition of a list of functions, each
consuming the return value of the function that follows.
@@ -3054,11 +3136,11 @@
underscore-esm.js
-
+
Returns a function that will only be executed on and after the Nth call.
@@ -3075,11 +3157,11 @@
underscore-esm.js
-
+
Returns a function that will only be executed up to (but not including) the
Nth call.
@@ -3100,11 +3182,11 @@
underscore-esm.js
-
+
Returns a function that will be executed at most one time, no matter how
often you call it. Useful for lazy initialization.
@@ -3116,11 +3198,11 @@
underscore-esm.js
-
+
Returns the first key on an object that passes a truth test.
@@ -3138,11 +3220,11 @@
underscore-esm.js
-
+
Internal function to generate _.findIndex and _.findLastIndex.
@@ -3163,11 +3245,11 @@
underscore-esm.js
-
+
Returns the first index on an array-like that passes a truth test.
@@ -3178,11 +3260,11 @@
underscore-esm.js
-
+
Returns the last index on an array-like that passes a truth test.
@@ -3193,11 +3275,11 @@
underscore-esm.js
-
+
Use a comparator function to figure out the smallest index at which
an object should be inserted so as to maintain order. Uses binary search.
@@ -3218,11 +3300,11 @@
underscore-esm.js
-
+
Internal function to generate the _.indexOf and _.lastIndexOf functions.
@@ -3255,11 +3337,11 @@
underscore-esm.js
-
+
Return the position of the first occurrence of an item in an array,
or -1 if the item is not included in the array.
@@ -3273,11 +3355,11 @@
underscore-esm.js
-
+
Return the position of the last occurrence of an item in an array,
or -1 if the item is not included in the array.
@@ -3289,11 +3371,11 @@
underscore-esm.js
-
+
Return the first value which passes a truth test.
@@ -3308,11 +3390,11 @@
underscore-esm.js
-
+
Convenience version of a common use case of _.find: getting the first
object containing specific key:value pairs.
@@ -3326,11 +3408,11 @@
underscore-esm.js
-
+
The cornerstone for collection functions, an each
implementation, aka forEach.
@@ -3358,11 +3440,11 @@
underscore-esm.js
-
+
Return the results of applying the iteratee to each element.
@@ -3383,11 +3465,11 @@
underscore-esm.js
-
+
Internal helper to create a reducing function, iterating left or right.
@@ -3398,11 +3480,11 @@
underscore-esm.js
-
+
Wrap code that reassigns argument variables in a separate function than
the one that accesses arguments.length to avoid a perf hit. (#1991)
@@ -3433,11 +3515,11 @@
underscore-esm.js
-
+
Reduce builds up a single result from a list of values, aka inject,
or foldl.
@@ -3449,11 +3531,11 @@
underscore-esm.js
-
+
The right-associative version of reduce, also known as foldr.
@@ -3464,11 +3546,11 @@
underscore-esm.js
-
+
Return all the elements that pass a truth test.
@@ -3486,11 +3568,11 @@
underscore-esm.js
-
+
Return all the elements for which a truth test fails.
@@ -3503,11 +3585,11 @@
underscore-esm.js
-
+
Determine whether all of the elements pass a truth test.
@@ -3527,11 +3609,11 @@
underscore-esm.js
-
+
Determine if at least one element in the object passes a truth test.
@@ -3551,11 +3633,11 @@
underscore-esm.js
-
+
Determine if the array or object contains a given item (using ===).
@@ -3570,11 +3652,11 @@
underscore-esm.js
-
+
Invoke a method (with arguments) on every item in a collection.
@@ -3605,11 +3687,11 @@
underscore-esm.js
-
+
Convenience version of a common use case of _.map: fetching a property.
@@ -3622,11 +3704,11 @@
underscore-esm.js
-
+
Convenience version of a common use case of _.filter: selecting only
objects containing specific key:value pairs.
@@ -3640,11 +3722,11 @@
underscore-esm.js
-
+
Return the maximum element (or element-based computation).
@@ -3677,11 +3759,11 @@
underscore-esm.js
-
+
Return the minimum element (or element-based computation).
@@ -3714,11 +3796,11 @@
underscore-esm.js
-
+
Safely create a real, live array from anything iterable.
@@ -3733,11 +3815,11 @@
underscore-esm.js
-
+
Keep surrogate pair characters together.
@@ -3752,11 +3834,11 @@
underscore-esm.js
-
+
Sample n random values from a collection using the modern version of the
Fisher-Yates shuffle.
@@ -3786,11 +3868,11 @@
underscore-esm.js
-
+
Shuffle a collection.
@@ -3803,11 +3885,11 @@
underscore-esm.js
-
+
Sort the object’s values by a criterion produced by an iteratee.
@@ -3836,11 +3918,11 @@
underscore-esm.js
-
+
An internal function used for aggregate “group by” operations.
@@ -3861,11 +3943,11 @@
underscore-esm.js
-
+
Groups the object’s values by a criterion. Pass either a string attribute
to group by, or a function that returns the criterion.
@@ -3879,11 +3961,11 @@
underscore-esm.js
-
+
Indexes the object’s values by a criterion, similar to _.groupBy, but for
when you know that your index values will be unique.
@@ -3897,11 +3979,11 @@
underscore-esm.js
-
+
Counts instances of an object that group by a certain criterion. Pass
either a string attribute to count by, or a function that returns the
@@ -3916,11 +3998,11 @@
underscore-esm.js
-
+
Split a collection into two arrays: one whose elements all pass the given
truth test, and one whose elements all do not pass the truth test.
@@ -3934,11 +4016,11 @@
underscore-esm.js
-
+
Return the number of elements in a collection.
@@ -3952,11 +4034,11 @@
underscore-esm.js
-
+
Internal _.pick helper function to determine whether key is an enumerable
property name of obj.
@@ -3970,11 +4052,11 @@
underscore-esm.js
-
+
Return a copy of the object only containing the allowed properties.
@@ -4002,11 +4084,11 @@
underscore-esm.js
-
+
Return a copy of the object without the disallowed properties.
@@ -4029,11 +4111,11 @@
underscore-esm.js
-
+
Returns everything but the last entry of the array. Especially useful on
the arguments object. Passing n will return all the values in
@@ -4048,11 +4130,11 @@
underscore-esm.js
-
+
Get the first element of an array. Passing n will return the first N
values in the array. The guard check allows it to work with _.map.
@@ -4068,11 +4150,11 @@
underscore-esm.js
-
+
Returns everything but the first entry of the array. Especially useful on
the arguments object. Passing an n will return the rest N values in the
@@ -4087,11 +4169,11 @@
underscore-esm.js
-
+
Get the last element of an array. Passing n will return the last N
values in the array.
@@ -4107,11 +4189,11 @@
underscore-esm.js
-
+
Trim out all falsy values from an array.
@@ -4124,11 +4206,11 @@
underscore-esm.js
-
+
Flatten out an array, either recursively (by default), or up to depth.
Passing true or false as depth means 1 or Infinity, respectively.
@@ -4142,11 +4224,11 @@
underscore-esm.js
-
+
Take the difference between one array and a number of other arrays.
Only the elements present in just the first array will remain.
@@ -4163,11 +4245,11 @@
underscore-esm.js
-
+
Return a version of the array that does not contain the specified value(s).
@@ -4180,11 +4262,11 @@
underscore-esm.js
-
+