UNPKG

10.7 kBJavaScriptView Raw
1/**
2 * lodash 4.0.6 (Custom Build) <https://lodash.com/>
3 * Build: `lodash modularize exports="npm" -o ./`
4 * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
5 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
6 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
7 * Available under MIT license <https://lodash.com/license>
8 */
9var keysIn = require('lodash.keysin'),
10 rest = require('lodash.rest');
11
12/** Used as references for various `Number` constants. */
13var MAX_SAFE_INTEGER = 9007199254740991;
14
15/** `Object#toString` result references. */
16var funcTag = '[object Function]',
17 genTag = '[object GeneratorFunction]';
18
19/** Used to detect unsigned integer values. */
20var reIsUint = /^(?:0|[1-9]\d*)$/;
21
22/**
23 * Checks if `value` is a valid array-like index.
24 *
25 * @private
26 * @param {*} value The value to check.
27 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
28 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
29 */
30function isIndex(value, length) {
31 value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
32 length = length == null ? MAX_SAFE_INTEGER : length;
33 return value > -1 && value % 1 == 0 && value < length;
34}
35
36/** Used for built-in method references. */
37var objectProto = Object.prototype;
38
39/** Used to check objects for own properties. */
40var hasOwnProperty = objectProto.hasOwnProperty;
41
42/**
43 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
44 * of values.
45 */
46var objectToString = objectProto.toString;
47
48/** Built-in value references. */
49var propertyIsEnumerable = objectProto.propertyIsEnumerable;
50
51/** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */
52var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf');
53
54/**
55 * Assigns `value` to `key` of `object` if the existing value is not equivalent
56 * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
57 * for equality comparisons.
58 *
59 * @private
60 * @param {Object} object The object to modify.
61 * @param {string} key The key of the property to assign.
62 * @param {*} value The value to assign.
63 */
64function assignValue(object, key, value) {
65 var objValue = object[key];
66 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
67 (value === undefined && !(key in object))) {
68 object[key] = value;
69 }
70}
71
72/**
73 * The base implementation of `_.property` without support for deep paths.
74 *
75 * @private
76 * @param {string} key The key of the property to get.
77 * @returns {Function} Returns the new function.
78 */
79function baseProperty(key) {
80 return function(object) {
81 return object == null ? undefined : object[key];
82 };
83}
84
85/**
86 * Copies properties of `source` to `object`.
87 *
88 * @private
89 * @param {Object} source The object to copy properties from.
90 * @param {Array} props The property names to copy.
91 * @param {Object} [object={}] The object to copy properties to.
92 * @returns {Object} Returns `object`.
93 */
94function copyObject(source, props, object) {
95 return copyObjectWith(source, props, object);
96}
97
98/**
99 * This function is like `copyObject` except that it accepts a function to
100 * customize copied values.
101 *
102 * @private
103 * @param {Object} source The object to copy properties from.
104 * @param {Array} props The property names to copy.
105 * @param {Object} [object={}] The object to copy properties to.
106 * @param {Function} [customizer] The function to customize copied values.
107 * @returns {Object} Returns `object`.
108 */
109function copyObjectWith(source, props, object, customizer) {
110 object || (object = {});
111
112 var index = -1,
113 length = props.length;
114
115 while (++index < length) {
116 var key = props[index];
117
118 var newValue = customizer
119 ? customizer(object[key], source[key], key, object, source)
120 : source[key];
121
122 assignValue(object, key, newValue);
123 }
124 return object;
125}
126
127/**
128 * Creates a function like `_.assign`.
129 *
130 * @private
131 * @param {Function} assigner The function to assign values.
132 * @returns {Function} Returns the new assigner function.
133 */
134function createAssigner(assigner) {
135 return rest(function(object, sources) {
136 var index = -1,
137 length = sources.length,
138 customizer = length > 1 ? sources[length - 1] : undefined,
139 guard = length > 2 ? sources[2] : undefined;
140
141 customizer = typeof customizer == 'function'
142 ? (length--, customizer)
143 : undefined;
144
145 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
146 customizer = length < 3 ? undefined : customizer;
147 length = 1;
148 }
149 object = Object(object);
150 while (++index < length) {
151 var source = sources[index];
152 if (source) {
153 assigner(object, source, index, customizer);
154 }
155 }
156 return object;
157 });
158}
159
160/**
161 * Gets the "length" property value of `object`.
162 *
163 * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
164 * that affects Safari on at least iOS 8.1-8.3 ARM64.
165 *
166 * @private
167 * @param {Object} object The object to query.
168 * @returns {*} Returns the "length" value.
169 */
170var getLength = baseProperty('length');
171
172/**
173 * Checks if the given arguments are from an iteratee call.
174 *
175 * @private
176 * @param {*} value The potential iteratee value argument.
177 * @param {*} index The potential iteratee index or key argument.
178 * @param {*} object The potential iteratee object argument.
179 * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
180 */
181function isIterateeCall(value, index, object) {
182 if (!isObject(object)) {
183 return false;
184 }
185 var type = typeof index;
186 if (type == 'number'
187 ? (isArrayLike(object) && isIndex(index, object.length))
188 : (type == 'string' && index in object)) {
189 return eq(object[index], value);
190 }
191 return false;
192}
193
194/**
195 * Checks if `value` is likely a prototype object.
196 *
197 * @private
198 * @param {*} value The value to check.
199 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
200 */
201function isPrototype(value) {
202 var Ctor = value && value.constructor,
203 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
204
205 return value === proto;
206}
207
208/**
209 * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
210 * comparison between two values to determine if they are equivalent.
211 *
212 * @static
213 * @memberOf _
214 * @category Lang
215 * @param {*} value The value to compare.
216 * @param {*} other The other value to compare.
217 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
218 * @example
219 *
220 * var object = { 'user': 'fred' };
221 * var other = { 'user': 'fred' };
222 *
223 * _.eq(object, object);
224 * // => true
225 *
226 * _.eq(object, other);
227 * // => false
228 *
229 * _.eq('a', 'a');
230 * // => true
231 *
232 * _.eq('a', Object('a'));
233 * // => false
234 *
235 * _.eq(NaN, NaN);
236 * // => true
237 */
238function eq(value, other) {
239 return value === other || (value !== value && other !== other);
240}
241
242/**
243 * Checks if `value` is array-like. A value is considered array-like if it's
244 * not a function and has a `value.length` that's an integer greater than or
245 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
246 *
247 * @static
248 * @memberOf _
249 * @category Lang
250 * @param {*} value The value to check.
251 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
252 * @example
253 *
254 * _.isArrayLike([1, 2, 3]);
255 * // => true
256 *
257 * _.isArrayLike(document.body.children);
258 * // => true
259 *
260 * _.isArrayLike('abc');
261 * // => true
262 *
263 * _.isArrayLike(_.noop);
264 * // => false
265 */
266function isArrayLike(value) {
267 return value != null && isLength(getLength(value)) && !isFunction(value);
268}
269
270/**
271 * Checks if `value` is classified as a `Function` object.
272 *
273 * @static
274 * @memberOf _
275 * @category Lang
276 * @param {*} value The value to check.
277 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
278 * @example
279 *
280 * _.isFunction(_);
281 * // => true
282 *
283 * _.isFunction(/abc/);
284 * // => false
285 */
286function isFunction(value) {
287 // The use of `Object#toString` avoids issues with the `typeof` operator
288 // in Safari 8 which returns 'object' for typed array and weak map constructors,
289 // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
290 var tag = isObject(value) ? objectToString.call(value) : '';
291 return tag == funcTag || tag == genTag;
292}
293
294/**
295 * Checks if `value` is a valid array-like length.
296 *
297 * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
298 *
299 * @static
300 * @memberOf _
301 * @category Lang
302 * @param {*} value The value to check.
303 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
304 * @example
305 *
306 * _.isLength(3);
307 * // => true
308 *
309 * _.isLength(Number.MIN_VALUE);
310 * // => false
311 *
312 * _.isLength(Infinity);
313 * // => false
314 *
315 * _.isLength('3');
316 * // => false
317 */
318function isLength(value) {
319 return typeof value == 'number' &&
320 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
321}
322
323/**
324 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
325 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
326 *
327 * @static
328 * @memberOf _
329 * @category Lang
330 * @param {*} value The value to check.
331 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
332 * @example
333 *
334 * _.isObject({});
335 * // => true
336 *
337 * _.isObject([1, 2, 3]);
338 * // => true
339 *
340 * _.isObject(_.noop);
341 * // => true
342 *
343 * _.isObject(null);
344 * // => false
345 */
346function isObject(value) {
347 var type = typeof value;
348 return !!value && (type == 'object' || type == 'function');
349}
350
351/**
352 * This method is like `_.assign` except that it iterates over own and
353 * inherited source properties.
354 *
355 * **Note:** This method mutates `object`.
356 *
357 * @static
358 * @memberOf _
359 * @alias extend
360 * @category Object
361 * @param {Object} object The destination object.
362 * @param {...Object} [sources] The source objects.
363 * @returns {Object} Returns `object`.
364 * @example
365 *
366 * function Foo() {
367 * this.b = 2;
368 * }
369 *
370 * function Bar() {
371 * this.d = 4;
372 * }
373 *
374 * Foo.prototype.c = 3;
375 * Bar.prototype.e = 5;
376 *
377 * _.assignIn({ 'a': 1 }, new Foo, new Bar);
378 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 }
379 */
380var assignIn = createAssigner(function(object, source) {
381 if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
382 copyObject(source, keysIn(source), object);
383 return;
384 }
385 for (var key in source) {
386 assignValue(object, key, source[key]);
387 }
388});
389
390module.exports = assignIn;