mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-07 10:07:48 +00:00
Ensure isType methods return false for subclassed values.
Former-commit-id: e300d12eb506c6ae4949bd37cf8eb33c3a4be2e1
This commit is contained in:
45
build.js
45
build.js
@@ -786,6 +786,19 @@
|
|||||||
return (source.match(/(?:\s*\/\/.*)*\n( *)if *\((?:!support\.argsClass|!isArguments)[\s\S]+?};\n\1}/) || [''])[0];
|
return (source.match(/(?:\s*\/\/.*)*\n( *)if *\((?:!support\.argsClass|!isArguments)[\s\S]+?};\n\1}/) || [''])[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the `_.isArray` fallback from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to inspect.
|
||||||
|
* @returns {String} Returns the `isArray` fallback.
|
||||||
|
*/
|
||||||
|
function getIsArrayFallback(source) {
|
||||||
|
return matchFunction(source, 'isArray')
|
||||||
|
.replace(/^[\s\S]+?=\s*nativeIsArray\b/, '')
|
||||||
|
.replace(/[;\s]+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `_.isFunction` fallback from `source`.
|
* Gets the `_.isFunction` fallback from `source`.
|
||||||
*
|
*
|
||||||
@@ -1016,6 +1029,17 @@
|
|||||||
return source.replace(getIsArgumentsFallback(source), '');
|
return source.replace(getIsArgumentsFallback(source), '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `_.isArray` fallback from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @returns {String} Returns the modified source.
|
||||||
|
*/
|
||||||
|
function removeIsArrayFallback(source) {
|
||||||
|
return source.replace(getIsArrayFallback(source), '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the `_.isFunction` fallback from `source`.
|
* Removes the `_.isFunction` fallback from `source`.
|
||||||
*
|
*
|
||||||
@@ -1074,11 +1098,6 @@
|
|||||||
function removeSupportArgsObject(source) {
|
function removeSupportArgsObject(source) {
|
||||||
source = removeSupportProp(source, 'argsObject');
|
source = removeSupportProp(source, 'argsObject');
|
||||||
|
|
||||||
// remove `argsAreObjects` from `_.isArray`
|
|
||||||
source = source.replace(matchFunction(source, 'isArray'), function(match) {
|
|
||||||
return match.replace(/\(support\.argsObject\s*&&\s*([^)]+)\)/g, '$1');
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove `argsAreObjects` from `_.isEqual`
|
// remove `argsAreObjects` from `_.isEqual`
|
||||||
source = source.replace(matchFunction(source, 'isEqual'), function(match) {
|
source = source.replace(matchFunction(source, 'isEqual'), function(match) {
|
||||||
return match.replace(/!support.\argsObject[^:]+:\s*/g, '');
|
return match.replace(/!support.\argsObject[^:]+:\s*/g, '');
|
||||||
@@ -1867,7 +1886,7 @@
|
|||||||
|
|
||||||
// remove native `Array.isArray` branch in `_.isArray`
|
// remove native `Array.isArray` branch in `_.isArray`
|
||||||
source = source.replace(matchFunction(source, 'isArray'), function(match) {
|
source = source.replace(matchFunction(source, 'isArray'), function(match) {
|
||||||
return match.replace(/\s*\(nativeIsArray.+/, ' toString.call(value) == arrayClass;');
|
return match.replace(/\bnativeIsArray\s*\|\|\s*/, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
// replace `_.keys` with `shimKeys`
|
// replace `_.keys` with `shimKeys`
|
||||||
@@ -1919,6 +1938,7 @@
|
|||||||
source = removeSupportNodeClass(source);
|
source = removeSupportNodeClass(source);
|
||||||
|
|
||||||
if (!isMobile) {
|
if (!isMobile) {
|
||||||
|
source = removeIsArrayFallback(source);
|
||||||
source = removeSupportEnumPrototypes(source);
|
source = removeSupportEnumPrototypes(source);
|
||||||
source = removeSupportNonEnumArgs(source);
|
source = removeSupportNonEnumArgs(source);
|
||||||
|
|
||||||
@@ -2006,11 +2026,6 @@
|
|||||||
source = source.replace(/^( *)var eachIteratorOptions *= *[\s\S]+?\n\1};\n/m, function(match) {
|
source = source.replace(/^( *)var eachIteratorOptions *= *[\s\S]+?\n\1};\n/m, function(match) {
|
||||||
return match.replace(/(^ *'arrays':)[^,]+/m, '$1 false');
|
return match.replace(/(^ *'arrays':)[^,]+/m, '$1 false');
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove `toString.call` use from `_.isArray`
|
|
||||||
source = source.replace(matchFunction(source, 'isArray'), function(match) {
|
|
||||||
return match.replace(/\s*\(nativeIsArray.+/, ' nativeIsArray(value);');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isUnderscore) {
|
if (isUnderscore) {
|
||||||
@@ -2535,14 +2550,6 @@
|
|||||||
return match.replace(/\bisEqual\(([^,]+), *([^,]+)[^)]+\)/, '$1 === $2');
|
return match.replace(/\bisEqual\(([^,]+), *([^,]+)[^)]+\)/, '$1 === $2');
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove `instanceof` use from `_.isDate`, `_.isFunction`, and `_.isRegExp`
|
|
||||||
_.each(['isDate', 'isFunction', 'isRegExp'], function(methodName) {
|
|
||||||
var snippet = methodName == 'isFunction' ? getIsFunctionFallback(source) : matchFunction(source, methodName);
|
|
||||||
source = source.replace(snippet, function(match) {
|
|
||||||
return match.replace(/\w+\s+instanceof\s+\w+\s*\|\|\s*/g, '');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove conditional `charCodeCallback` use from `_.max` and `_.min`
|
// remove conditional `charCodeCallback` use from `_.max` and `_.min`
|
||||||
_.each(['max', 'min'], function(methodName) {
|
_.each(['max', 'min'], function(methodName) {
|
||||||
source = source.replace(matchFunction(source, methodName), function(match) {
|
source = source.replace(matchFunction(source, methodName), function(match) {
|
||||||
|
|||||||
49
lodash.js
49
lodash.js
@@ -943,6 +943,26 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is an array.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Objects
|
||||||
|
* @param {Mixed} value The value to check.
|
||||||
|
* @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* (function() { return _.isArray(arguments); })();
|
||||||
|
* // => false
|
||||||
|
*
|
||||||
|
* _.isArray([1, 2, 3]);
|
||||||
|
* // => true
|
||||||
|
*/
|
||||||
|
var isArray = nativeIsArray || function(value) {
|
||||||
|
return value && typeof value == 'object' && toString.call(value) == arrayClass;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fallback implementation of `Object.keys` which produces an array of the
|
* A fallback implementation of `Object.keys` which produces an array of the
|
||||||
* given object's own enumerable property names.
|
* given object's own enumerable property names.
|
||||||
@@ -1416,29 +1436,6 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if `value` is an array.
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @memberOf _
|
|
||||||
* @category Objects
|
|
||||||
* @param {Mixed} value The value to check.
|
|
||||||
* @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
|
|
||||||
* @example
|
|
||||||
*
|
|
||||||
* (function() { return _.isArray(arguments); })();
|
|
||||||
* // => false
|
|
||||||
*
|
|
||||||
* _.isArray([1, 2, 3]);
|
|
||||||
* // => true
|
|
||||||
*/
|
|
||||||
function isArray(value) {
|
|
||||||
// `instanceof` may cause a memory leak in IE 7 if `value` is a host object
|
|
||||||
// http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
|
|
||||||
return (support.argsObject && value instanceof Array) ||
|
|
||||||
(nativeIsArray ? nativeIsArray(value) : toString.call(value) == arrayClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is a boolean value.
|
* Checks if `value` is a boolean value.
|
||||||
*
|
*
|
||||||
@@ -1470,7 +1467,7 @@
|
|||||||
* // => true
|
* // => true
|
||||||
*/
|
*/
|
||||||
function isDate(value) {
|
function isDate(value) {
|
||||||
return value instanceof Date || toString.call(value) == dateClass;
|
return value ? typeof value == 'object' && toString.call(value) == dateClass : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1774,7 +1771,7 @@
|
|||||||
// fallback for older versions of Chrome and Safari
|
// fallback for older versions of Chrome and Safari
|
||||||
if (isFunction(/x/)) {
|
if (isFunction(/x/)) {
|
||||||
isFunction = function(value) {
|
isFunction = function(value) {
|
||||||
return value instanceof Function || toString.call(value) == funcClass;
|
return typeof value == 'function' && toString.call(value) == funcClass;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1924,7 +1921,7 @@
|
|||||||
* // => true
|
* // => true
|
||||||
*/
|
*/
|
||||||
function isRegExp(value) {
|
function isRegExp(value) {
|
||||||
return value instanceof RegExp || toString.call(value) == regexpClass;
|
return value ? typeof value == 'object' && toString.call(value) == regexpClass : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -961,11 +961,6 @@
|
|||||||
|
|
||||||
strictEqual(actual, false, '_.isEqual should ignore `callback` and `thisArg`: ' + basename);
|
strictEqual(actual, false, '_.isEqual should ignore `callback` and `thisArg`: ' + basename);
|
||||||
|
|
||||||
_.each(['isArray', 'isBoolean', 'isDate', 'isFunction', 'isNumber', 'isRegExp', 'isString'], function(methodName) {
|
|
||||||
var proto = global[methodName.slice(2)].prototype;
|
|
||||||
strictEqual(lodash[methodName](Object.create(proto)), false, '_.' + methodName + ' returns `false` for subclassed values: ' + basename);
|
|
||||||
});
|
|
||||||
|
|
||||||
equal(lodash.max('abc'), -Infinity, '_.max should return `-Infinity` for strings: ' + basename);
|
equal(lodash.max('abc'), -Infinity, '_.max should return `-Infinity` for strings: ' + basename);
|
||||||
equal(lodash.min('abc'), Infinity, '_.min should return `Infinity` for strings: ' + basename);
|
equal(lodash.min('abc'), Infinity, '_.min should return `Infinity` for strings: ' + basename);
|
||||||
|
|
||||||
|
|||||||
@@ -1611,6 +1611,15 @@
|
|||||||
equal(typeof func({ 'a': 1 }), expected);
|
equal(typeof func({ 'a': 1 }), expected);
|
||||||
equal(typeof func('a'), expected);
|
equal(typeof func('a'), expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should return `false` for subclassed values', function() {
|
||||||
|
_.each(['isArray', 'isBoolean', 'isDate', 'isFunction', 'isNumber', 'isRegExp', 'isString'], function(methodName) {
|
||||||
|
function Foo() {}
|
||||||
|
Foo.prototype = window[methodName.slice(2)].prototype;
|
||||||
|
|
||||||
|
strictEqual(_[methodName](new Foo), false, '_.' + methodName + ' returns `false`');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user