/** * lodash 3.0.0 (Custom Build) * Build: `lodash modern modularize exports="npm" -o ./` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.7.0 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ var arrayCopy = require('lodash._arraycopy'), arrayEach = require('lodash._arrayeach'), baseFor = require('lodash._basefor'), createAssigner = require('lodash._createassigner'), isArguments = require('lodash.isarguments'), isArray = require('lodash.isarray'), isPlainObject = require('lodash.isplainobject'), isTypedArray = require('lodash.istypedarray'), keys = require('lodash.keys'), toPlainObject = require('lodash.toplainobject'); /** * Checks if `value` is object-like. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { return (value && typeof value == 'object') || false; } /** * Used as the maximum length of an array-like value. * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * for more details. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; /** * The base implementation of `_.forOwn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return baseFor(object, iteratee, keys); } /** * The base implementation of `_.merge` without support for argument juggling, * multiple sources, and `this` binding `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns the destination object. */ function baseMerge(object, source, customizer, stackA, stackB) { var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source)); (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { if (isObjectLike(srcValue)) { stackA || (stackA = []); stackB || (stackB = []); return baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); } var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = typeof result == 'undefined'; if (isCommon) { result = srcValue; } if ((isSrcArr || typeof result != 'undefined') && (isCommon || (result === result ? result !== value : value === value))) { object[key] = result; } }); return object; } /** * A specialized version of `baseMerge` for arrays and objects which performs * deep merges and tracks traversed objects enabling objects with circular * references to be merged. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { var length = stackA.length, srcValue = source[key]; while (length--) { if (stackA[length] == srcValue) { object[key] = stackB[length]; return; } } var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = typeof result == 'undefined'; if (isCommon) { result = srcValue; if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { result = isArray(value) ? value : (value ? arrayCopy(value) : []); } else if (isPlainObject(srcValue) || isArguments(srcValue)) { result = isArguments(value) ? toPlainObject(value) : (isPlainObject(value) ? value : {}); } } // Add the source value to the stack of traversed objects and associate // it with its merged value. stackA.push(srcValue); stackB.push(result); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); } else if (result === result ? result !== value : value === value) { object[key] = result; } } /** * Checks if `value` is a valid array-like length. * * **Note:** This function is based on ES `ToLength`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) * for more details. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. */ function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is * provided it is invoked to produce the merged values of the destination and * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns `object`. * @example * * var users = { * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] * }; * * var ages = { * 'data': [{ 'age': 36 }, { 'age': 40 }] * }; * * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } * * // using a customizer callback * var object = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var other = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * _.merge(object, other, function(a, b) { * return _.isArray(a) ? a.concat(b) : undefined; * }); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ var merge = createAssigner(baseMerge); module.exports = merge;