mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 02:47:50 +00:00
Cleanup _.isEqual comments and ensure _.isEmpty/_.size detect arguments objects correctly.
Former-commit-id: 75b044d27b990d55393bf27234aad6ce369f6abe
This commit is contained in:
20
build.js
20
build.js
@@ -51,6 +51,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isLegacy) {
|
if (isLegacy) {
|
||||||
|
source = replaceVar(source, 'noArgsClass', 'true');
|
||||||
['isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
|
['isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
|
||||||
source = replaceVar(source, varName, 'false');
|
source = replaceVar(source, varName, 'false');
|
||||||
});
|
});
|
||||||
@@ -401,7 +402,7 @@
|
|||||||
* @returns {String} Returns the `isArguments` fallback snippet.
|
* @returns {String} Returns the `isArguments` fallback snippet.
|
||||||
*/
|
*/
|
||||||
function getIsArgumentsFallback(source) {
|
function getIsArgumentsFallback(source) {
|
||||||
return (source.match(/(?:\s*\/\/.*)*\s*if *\(!(?:lodash\.)?isArguments[^)]+\)[\s\S]+?};\s*}/) || [''])[0];
|
return (source.match(/(?:\s*\/\/.*)*\s*if *\(noArgsClass[\s\S]+?};\s*}/) || [''])[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -773,15 +774,15 @@
|
|||||||
|
|
||||||
// build replacement code
|
// build replacement code
|
||||||
lodash.forOwn({
|
lodash.forOwn({
|
||||||
'Arguments': "'[object Arguments]'",
|
'Arguments': 'argsClass',
|
||||||
'Date': 'dateClass',
|
'Date': 'dateClass',
|
||||||
'Function': 'funcClass',
|
'Function': 'funcClass',
|
||||||
'Number': 'numberClass',
|
'Number': 'numberClass',
|
||||||
'RegExp': 'regexpClass',
|
'RegExp': 'regexpClass',
|
||||||
'String': 'stringClass'
|
'String': 'stringClass'
|
||||||
}, function(value, key) {
|
}, function(value, key) {
|
||||||
// skip `isArguments` if a legacy build
|
// skip `isArguments` if not a mobile build
|
||||||
if (isLegacy && key == 'Arguments') {
|
if (!isMobile && key == 'Arguments') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var funcName = 'is' + key,
|
var funcName = 'is' + key,
|
||||||
@@ -818,13 +819,6 @@
|
|||||||
' };\n' +
|
' };\n' +
|
||||||
' });'
|
' });'
|
||||||
);
|
);
|
||||||
|
|
||||||
// tweak `isArguments` fallback
|
|
||||||
snippet = !isLegacy && getIsArgumentsFallback(source);
|
|
||||||
if (snippet) {
|
|
||||||
var modified = '\n' + snippet.replace(/isArguments/g, 'lodash.$&');
|
|
||||||
source = source.replace(snippet, modified);
|
|
||||||
}
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -861,8 +855,8 @@
|
|||||||
// replace `_.isArguments` with fallback
|
// replace `_.isArguments` with fallback
|
||||||
if (!isRemoved(source, 'isArguments')) {
|
if (!isRemoved(source, 'isArguments')) {
|
||||||
source = source.replace(
|
source = source.replace(
|
||||||
matchFunction(source, 'isArguments').replace(/[\s\S]+?var isArguments *=/, ''),
|
matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
|
||||||
getIsArgumentsFallback(source).match(/isArguments *=([\s\S]+?) *};/)[1] + ' };\n'
|
getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n'
|
||||||
);
|
);
|
||||||
|
|
||||||
source = removeIsArgumentsFallback(source);
|
source = removeIsArgumentsFallback(source);
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
'accumulator',
|
'accumulator',
|
||||||
'args',
|
'args',
|
||||||
'arrayClass',
|
'arrayClass',
|
||||||
|
'arrayLikeClasses',
|
||||||
'ArrayProto',
|
'ArrayProto',
|
||||||
'bind',
|
'bind',
|
||||||
'callback',
|
'callback',
|
||||||
'className',
|
|
||||||
'collection',
|
'collection',
|
||||||
'compareAscending',
|
'compareAscending',
|
||||||
'concat',
|
'concat',
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
'identity',
|
'identity',
|
||||||
'index',
|
'index',
|
||||||
'indexOf',
|
'indexOf',
|
||||||
|
'isArguments',
|
||||||
'isFunc',
|
'isFunc',
|
||||||
'iteratee',
|
'iteratee',
|
||||||
'iterateeIndex',
|
'iterateeIndex',
|
||||||
@@ -215,6 +216,10 @@
|
|||||||
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
||||||
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
||||||
|
|
||||||
|
// manually convert `arrayLikeClasses` property assignments because
|
||||||
|
// Closure Compiler errors trying to minify them
|
||||||
|
source = source.replace(/(arrayLikeClasses =)[\s\S]+?= *true/g, "$1{'[object Arguments]': true, '[object Array]': true, '[object String]': true }");
|
||||||
|
|
||||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
||||||
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||||
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
||||||
@@ -239,7 +244,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove whitespace from `_.template` related regexpes
|
// remove whitespace from `_.template` related regexes
|
||||||
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
||||||
return match.replace(/ |\\n/g, '');
|
return match.replace(/ |\\n/g, '');
|
||||||
});
|
});
|
||||||
@@ -346,7 +351,7 @@
|
|||||||
else {
|
else {
|
||||||
// minify property name strings
|
// minify property name strings
|
||||||
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
||||||
// minify property names in regexps and accessors
|
// minify property names in regexes and accessors
|
||||||
if (isCreateIterator) {
|
if (isCreateIterator) {
|
||||||
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
||||||
}
|
}
|
||||||
|
|||||||
107
lodash.js
107
lodash.js
@@ -104,7 +104,8 @@
|
|||||||
nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys;
|
nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys;
|
||||||
|
|
||||||
/** `Object#toString` result shortcuts */
|
/** `Object#toString` result shortcuts */
|
||||||
var arrayClass = '[object Array]',
|
var argsClass = '[object Arguments]',
|
||||||
|
arrayClass = '[object Array]',
|
||||||
boolClass = '[object Boolean]',
|
boolClass = '[object Boolean]',
|
||||||
dateClass = '[object Date]',
|
dateClass = '[object Date]',
|
||||||
funcClass = '[object Function]',
|
funcClass = '[object Function]',
|
||||||
@@ -123,6 +124,9 @@
|
|||||||
*/
|
*/
|
||||||
var hasDontEnumBug = !propertyIsEnumerable.call({ 'valueOf': 0 }, 'valueOf');
|
var hasDontEnumBug = !propertyIsEnumerable.call({ 'valueOf': 0 }, 'valueOf');
|
||||||
|
|
||||||
|
/** Detect if an `arguments` object's [[Class]] is unresolvable (Firefox < 4, IE < 9) */
|
||||||
|
var noArgsClass = !isArguments(arguments);
|
||||||
|
|
||||||
/** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
|
/** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
|
||||||
var noArraySliceOnStrings = slice.call('x')[0] != 'x';
|
var noArraySliceOnStrings = slice.call('x')[0] != 'x';
|
||||||
|
|
||||||
@@ -136,7 +140,7 @@
|
|||||||
/* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
|
/* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
|
||||||
var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
|
var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
|
||||||
|
|
||||||
/* Detect if `Object.keys` exists and is inferred to be fast (V8, Opera, IE) */
|
/* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
|
||||||
var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
|
var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
|
||||||
|
|
||||||
/** Detect if sourceURL syntax is usable without erroring */
|
/** Detect if sourceURL syntax is usable without erroring */
|
||||||
@@ -151,6 +155,10 @@
|
|||||||
var useSourceURL = (Function('//@cc_on!')(), true);
|
var useSourceURL = (Function('//@cc_on!')(), true);
|
||||||
} catch(e){ }
|
} catch(e){ }
|
||||||
|
|
||||||
|
/** Used to identify object classifications that are array-like */
|
||||||
|
var arrayLikeClasses = {};
|
||||||
|
arrayLikeClasses[argsClass] = arrayLikeClasses[arrayClass] = arrayLikeClasses[stringClass] = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to escape characters for inclusion in HTML.
|
* Used to escape characters for inclusion in HTML.
|
||||||
* The `>` and `/` characters don't require escaping in HTML and have no
|
* The `>` and `/` characters don't require escaping in HTML and have no
|
||||||
@@ -592,16 +600,16 @@
|
|||||||
}
|
}
|
||||||
// create the function factory
|
// create the function factory
|
||||||
var factory = Function(
|
var factory = Function(
|
||||||
'arrayClass, ArrayProto, bind, compareAscending, concat, funcClass, ' +
|
'arrayClass, arrayLikeClasses, ArrayProto, bind, compareAscending, concat, ' +
|
||||||
'hasOwnProperty, identity, indexOf, iteratorBind, objectTypes, nativeKeys, ' +
|
'funcClass, hasOwnProperty, identity, indexOf, isArguments, iteratorBind, ' +
|
||||||
'propertyIsEnumerable, slice, stringClass, toString',
|
'objectTypes, nativeKeys, propertyIsEnumerable, slice, stringClass, toString',
|
||||||
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
||||||
);
|
);
|
||||||
// return the compiled function
|
// return the compiled function
|
||||||
return factory(
|
return factory(
|
||||||
arrayClass, ArrayProto, bind, compareAscending, concat, funcClass,
|
arrayClass, arrayLikeClasses, ArrayProto, bind, compareAscending, concat,
|
||||||
hasOwnProperty, identity, indexOf, iteratorBind, objectTypes, nativeKeys,
|
funcClass, hasOwnProperty, identity, indexOf, isArguments, iteratorBind,
|
||||||
propertyIsEnumerable, slice, stringClass, toString
|
objectTypes, nativeKeys, propertyIsEnumerable, slice, stringClass, toString
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2650,12 +2658,11 @@
|
|||||||
* _.isArguments([1, 2, 3]);
|
* _.isArguments([1, 2, 3]);
|
||||||
* // => false
|
* // => false
|
||||||
*/
|
*/
|
||||||
var isArguments = function(value) {
|
function isArguments(value) {
|
||||||
return toString.call(value) == '[object Arguments]';
|
return toString.call(value) == argsClass;
|
||||||
};
|
}
|
||||||
// fallback for browser like Firefox < 4 and IE < 9 which detect
|
// fallback for browsers that can't detect `arguments` objects by [[Class]]
|
||||||
// `arguments` as `[object Object]`
|
if (noArgsClass) {
|
||||||
if (!isArguments(arguments)) {
|
|
||||||
isArguments = function(value) {
|
isArguments = function(value) {
|
||||||
return !!(value && hasOwnProperty.call(value, 'callee'));
|
return !!(value && hasOwnProperty.call(value, 'callee'));
|
||||||
};
|
};
|
||||||
@@ -2733,8 +2740,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is empty. Arrays or strings with a length of `0` and
|
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
|
||||||
* objects with no own enumerable properties are considered "empty".
|
* length of `0` and objects with no own enumerable properties are considered
|
||||||
|
* "empty".
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
@@ -2756,8 +2764,9 @@
|
|||||||
'args': 'value',
|
'args': 'value',
|
||||||
'init': 'true',
|
'init': 'true',
|
||||||
'top':
|
'top':
|
||||||
'var className = toString.call(value);\n' +
|
'if (arrayLikeClasses[toString.call(value)]' +
|
||||||
'if (className == arrayClass || className == stringClass) return !value.length',
|
(noArgsClass ? ' || isArguments(value)' : '') +
|
||||||
|
') return !value.length',
|
||||||
'inLoop': {
|
'inLoop': {
|
||||||
'object': 'return false'
|
'object': 'return false'
|
||||||
}
|
}
|
||||||
@@ -2794,7 +2803,7 @@
|
|||||||
// treat `+0` vs. `-0` as not equal
|
// treat `+0` vs. `-0` as not equal
|
||||||
return a !== 0 || (1 / a == 1 / b);
|
return a !== 0 || (1 / a == 1 / b);
|
||||||
}
|
}
|
||||||
// a strict comparison is necessary because `undefined == null`
|
// a strict comparison is necessary because `null == undefined`
|
||||||
if (a == null || b == null) {
|
if (a == null || b == null) {
|
||||||
return a === b;
|
return a === b;
|
||||||
}
|
}
|
||||||
@@ -2818,11 +2827,11 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (className) {
|
switch (className) {
|
||||||
// strings, numbers, dates, and booleans are compared by value
|
case boolClass:
|
||||||
case stringClass:
|
case dateClass:
|
||||||
// primitives and their corresponding object instances are equivalent;
|
// coerce dates and booleans to numbers, dates to milliseconds and booleans
|
||||||
// thus, `'5'` is quivalent to `new String('5')`
|
// to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
|
||||||
return a == String(b);
|
return +a == +b;
|
||||||
|
|
||||||
case numberClass:
|
case numberClass:
|
||||||
// treat `NaN` vs. `NaN` as equal
|
// treat `NaN` vs. `NaN` as equal
|
||||||
@@ -2831,28 +2840,21 @@
|
|||||||
// but treat `+0` vs. `-0` as not equal
|
// but treat `+0` vs. `-0` as not equal
|
||||||
: (a == 0 ? (1 / a == 1 / b) : a == +b);
|
: (a == 0 ? (1 / a == 1 / b) : a == +b);
|
||||||
|
|
||||||
case boolClass:
|
|
||||||
case dateClass:
|
|
||||||
// coerce dates and booleans to numeric values, dates to milliseconds and
|
|
||||||
// booleans to 1 or 0; treat invalid dates coerced to `NaN` as not equal
|
|
||||||
return +a == +b;
|
|
||||||
|
|
||||||
// regexps are compared by their source and flags
|
|
||||||
case regexpClass:
|
case regexpClass:
|
||||||
return a.source == b.source &&
|
case stringClass:
|
||||||
a.global == b.global &&
|
// coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
|
||||||
a.multiline == b.multiline &&
|
// treat string primitives and their corresponding object instances as equal
|
||||||
a.ignoreCase == b.ignoreCase;
|
return a == b + '';
|
||||||
}
|
}
|
||||||
if (typeof a != 'object' || typeof b != 'object') {
|
if (typeof a != 'object' || typeof b != 'object') {
|
||||||
|
// for unequal function values
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
// assume cyclic structures are equal
|
||||||
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
// the algorithm for detecting cyclic structures is adapted from ES 5.1
|
||||||
|
// section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
|
||||||
var length = stack.length;
|
var length = stack.length;
|
||||||
while (length--) {
|
while (length--) {
|
||||||
// Linear search. Performance is inversely proportional to the number of
|
|
||||||
// unique nested structures.
|
|
||||||
if (stack[length] == a) {
|
if (stack[length] == a) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2865,7 +2867,7 @@
|
|||||||
// add the first collection to the stack of traversed objects
|
// add the first collection to the stack of traversed objects
|
||||||
stack.push(a);
|
stack.push(a);
|
||||||
|
|
||||||
// recursively compare objects and arrays
|
// recursively compare objects and arrays (susceptible to call stack limits)
|
||||||
if (className == arrayClass) {
|
if (className == arrayClass) {
|
||||||
// compare array lengths to determine if a deep comparison is necessary
|
// compare array lengths to determine if a deep comparison is necessary
|
||||||
size = a.length;
|
size = a.length;
|
||||||
@@ -2881,11 +2883,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// objects with different constructors are not equivalent
|
// objects with different constructors are not equal
|
||||||
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
|
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// deep compare objects.
|
// deep compare objects
|
||||||
for (var prop in a) {
|
for (var prop in a) {
|
||||||
if (hasOwnProperty.call(a, prop)) {
|
if (hasOwnProperty.call(a, prop)) {
|
||||||
// count the number of properties.
|
// count the number of properties.
|
||||||
@@ -2899,14 +2901,14 @@
|
|||||||
// ensure both objects have the same number of properties
|
// ensure both objects have the same number of properties
|
||||||
if (result) {
|
if (result) {
|
||||||
for (prop in b) {
|
for (prop in b) {
|
||||||
// Adobe's JS engine, embedded in applications like InDesign, has a
|
// The JS engine in Adobe products, like InDesign, has a bug that causes
|
||||||
// bug that causes `!size--` to throw an error so it must be wrapped
|
// `!size--` to throw an error so it must be wrapped in parentheses.
|
||||||
// in parentheses.
|
|
||||||
// https://github.com/documentcloud/underscore/issues/355
|
// https://github.com/documentcloud/underscore/issues/355
|
||||||
if (hasOwnProperty.call(b, prop) && !(size--)) {
|
if (hasOwnProperty.call(b, prop) && !(size--)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// `size` will be `-1` if `b` has more properties than `a`
|
||||||
result = !size;
|
result = !size;
|
||||||
}
|
}
|
||||||
// handle JScript [[DontEnum]] bug
|
// handle JScript [[DontEnum]] bug
|
||||||
@@ -2971,7 +2973,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is the language type of Object.
|
* Checks if `value` is the language type of Object.
|
||||||
* (e.g. arrays, functions, objects, regexps, `new Number(0)`, and `new String('')`)
|
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
@@ -3167,16 +3169,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the size of `value` by returning `value.length` if `value` is a string
|
* Gets the size of `value` by returning `value.length` if `value` is an
|
||||||
* or array, or the number of own enumerable properties if `value` is an object.
|
* array, string, or `arguments` object. If `value` is an object, size is
|
||||||
|
* determined by returning the number of own enumerable properties it has.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Objects
|
* @category Objects
|
||||||
* @param {Array|Object|String} value The value to inspect.
|
* @param {Array|Object|String} value The value to inspect.
|
||||||
* @returns {Number} Returns `value.length` if `value` is a string or array,
|
* @returns {Number} Returns `value.length` or number of own enumerable properties.
|
||||||
* or the number of own enumerable properties if `value` is an object.
|
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* _.size([1, 2]);
|
* _.size([1, 2]);
|
||||||
@@ -3192,8 +3194,9 @@
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var length = value.length;
|
return arrayLikeClasses[toString.call(value)] || (noArgsClass && isArguments(value))
|
||||||
return length === length >>> 0 ? value.length : keys(value).length;
|
? value.length
|
||||||
|
: keys(value).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
16
test/test.js
16
test/test.js
@@ -546,6 +546,8 @@
|
|||||||
QUnit.module('lodash.isEmpty');
|
QUnit.module('lodash.isEmpty');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
var args = arguments;
|
||||||
|
|
||||||
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
|
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
|
||||||
equal(_.isEmpty(shadowed), false);
|
equal(_.isEmpty(shadowed), false);
|
||||||
});
|
});
|
||||||
@@ -558,7 +560,15 @@
|
|||||||
Foo.prototype = { 'a': 1 };
|
Foo.prototype = { 'a': 1 };
|
||||||
equal(_.isEmpty(Foo), true);
|
equal(_.isEmpty(Foo), true);
|
||||||
});
|
});
|
||||||
}());
|
|
||||||
|
test('should work with an object that has a `length` property', function() {
|
||||||
|
equal(_.isEmpty({ 'length': 0 }), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with `arguments` objects (test in IE < 9)', function() {
|
||||||
|
equal(_.isEmpty(args), false);
|
||||||
|
});
|
||||||
|
}(1, 2, 3));
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -784,6 +794,10 @@
|
|||||||
deepEqual(actual, [0, 0, 0, 0, 0]);
|
deepEqual(actual, [0, 0, 0, 0, 0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with an object that has a `length` property', function() {
|
||||||
|
equal(_.size({ 'length': 3 }), 1);
|
||||||
|
});
|
||||||
|
|
||||||
test('should work with `arguments` objects (test in IE < 9)', function() {
|
test('should work with `arguments` objects (test in IE < 9)', function() {
|
||||||
equal(_.size(args), 3);
|
equal(_.size(args), 3);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user