diff --git a/build.js b/build.js index 667ccfa91..90345d63d 100755 --- a/build.js +++ b/build.js @@ -435,7 +435,7 @@ * @returns {String} Returns the `isArguments` fallback snippet. */ function getIsArgumentsFallback(source) { - return (source.match(/(?:\s*\/\/.*)*\s*if *\(noArgsClass[\s\S]+?};\s*}/) || [''])[0]; + return (source.match(/(?:\s*\/\/.*)*\n( +)if *\(noArgsClass[\s\S]+?};\n\1}/) || [''])[0]; } /** @@ -563,7 +563,18 @@ * @returns {String} Returns the source with the `isFunction` fallback removed. */ function removeIsFunctionFallback(source) { - return source.replace(/(?:\s*\/\/.*)*\s*if *\(isFunction\(\/x\/[\s\S]+?};\s*}/, ''); + return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/, ''); + } + + /** + * Removes the `isPlainObject` fallback from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the source with the `isPlainObject` fallback removed. + */ + function removeIsPlainObjectFallback(source) { + return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(!isPlainObject[\s\S]+?};\n\1}/, ''); } /** @@ -984,6 +995,11 @@ return match.replace(/\bcallee\b/g, 'merge'); }); + if (!isUnderscore) { + source = removeIsArgumentsFallback(source); + source = removeIsPlainObjectFallback(source); + } + // remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, `noArgsEnum` assignment source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b[\s\S]+?}\(1\)\);\n/, ''); @@ -1006,7 +1022,6 @@ source = removeVar(source, 'iteratorTemplate'); source = removeVar(source, 'noArraySliceOnStrings'); source = removeVar(source, 'noCharByIndex'); - source = removeIsArgumentsFallback(source); source = removeKeysOptimization(source); source = removeNoArgsClass(source); source = removeNoNodeClass(source); diff --git a/build/pre-compile.js b/build/pre-compile.js index 31bf03fd6..6e5f4bcb8 100644 --- a/build/pre-compile.js +++ b/build/pre-compile.js @@ -106,6 +106,7 @@ '_', '_chain', '_wrapped', + '__proto__', 'after', 'all', 'amd', diff --git a/lodash.js b/lodash.js index 7664e7bf6..bc6aae255 100644 --- a/lodash.js +++ b/lodash.js @@ -798,51 +798,6 @@ return htmlEscapes[match]; } - /** - * Checks if a given `value` is an object created by the `Object` constructor - * assuming objects created by the `Object` constructor have no inherited - * enumerable properties and that there are no `Object.prototype` extensions. - * - * @private - * @param {Mixed} value The value to check. - * @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for - * `arguments` objects. - * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, - * else `false`. - */ - function isPlainObject(value, skipArgsCheck) { - // avoid non-objects and false positives for `arguments` objects - var result = false; - if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) { - return result; - } - // IE < 9 presents DOM nodes as `Object` objects except they have `toString` - // methods that are `typeof` "string" and still can coerce nodes to strings. - // Also check that the constructor is `Object` (i.e. `Object instanceof Object`) - var ctor = value.constructor; - if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) && - (!isFunction(ctor) || ctor instanceof ctor)) { - // IE < 9 iterates inherited properties before own properties. If the first - // iterated property is an object's own property then there are no inherited - // enumerable properties. - if (iteratesOwnLast) { - forIn(value, function(objValue, objKey) { - result = !hasOwnProperty.call(value, objKey); - return false; - }); - return result === false; - } - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - forIn(value, function(objValue, objKey) { - result = objKey; - }); - return result === false || hasOwnProperty.call(value, result); - } - return result; - } - /** * Creates a new function that, when called, invokes `func` with the `this` * binding of `thisArg` and the arguments (value, index, object). @@ -1005,6 +960,59 @@ }; } + /** + * Checks if a given `value` is an object created by the `Object` constructor + * assuming objects created by the `Object` constructor have no inherited + * enumerable properties and that there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for + * `arguments` objects. + * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, + * else `false`. + */ + function isPlainObject(value, skipArgsCheck) { + return value + ? value == ObjectProto || (value.__proto__ == ObjectProto && (skipArgsCheck || !isArguments(value))) + : false; + } + // fallback for IE + if (!isPlainObject(objectTypes)) { + isPlainObject = function(value, skipArgsCheck) { + // avoid non-objects and false positives for `arguments` objects + var result = false; + if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) { + return result; + } + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings. + // Also check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) && + (!isFunction(ctor) || ctor instanceof ctor)) { + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + if (iteratesOwnLast) { + forIn(value, function(objValue, objKey) { + result = !hasOwnProperty.call(value, objKey); + return false; + }); + return result === false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + forIn(value, function(objValue, objKey) { + result = objKey; + }); + return result === false || hasOwnProperty.call(value, result); + } + return result; + }; + } + /** * A shim implementation of `Object.keys` that produces an array of the given * object's own enumerable property names.