1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/util/object.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,92 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +module.metadata = { 1.11 + "stability": "unstable" 1.12 +}; 1.13 + 1.14 +const { flatten } = require('./array'); 1.15 + 1.16 +/** 1.17 + * Merges all the properties of all arguments into first argument. If two or 1.18 + * more argument objects have own properties with the same name, the property 1.19 + * is overridden, with precedence from right to left, implying, that properties 1.20 + * of the object on the left are overridden by a same named property of the 1.21 + * object on the right. 1.22 + * 1.23 + * Any argument given with "falsy" value - commonly `null` and `undefined` in 1.24 + * case of objects - are skipped. 1.25 + * 1.26 + * @examples 1.27 + * var a = { bar: 0, a: 'a' } 1.28 + * var b = merge(a, { foo: 'foo', bar: 1 }, { foo: 'bar', name: 'b' }); 1.29 + * b === a // true 1.30 + * b.a // 'a' 1.31 + * b.foo // 'bar' 1.32 + * b.bar // 1 1.33 + * b.name // 'b' 1.34 + */ 1.35 +function merge(source) { 1.36 + let descriptor = {}; 1.37 + 1.38 + // `Boolean` converts the first parameter to a boolean value. Any object is 1.39 + // converted to `true` where `null` and `undefined` becames `false`. Therefore 1.40 + // the `filter` method will keep only objects that are defined and not null. 1.41 + Array.slice(arguments, 1).filter(Boolean).forEach(function onEach(properties) { 1.42 + Object.getOwnPropertyNames(properties).forEach(function(name) { 1.43 + descriptor[name] = Object.getOwnPropertyDescriptor(properties, name); 1.44 + }); 1.45 + }); 1.46 + return Object.defineProperties(source, descriptor); 1.47 +} 1.48 +exports.merge = merge; 1.49 + 1.50 +/** 1.51 + * Returns an object that inherits from the first argument and contains all the 1.52 + * properties from all following arguments. 1.53 + * `extend(source1, source2, source3)` is equivalent of 1.54 + * `merge(Object.create(source1), source2, source3)`. 1.55 + */ 1.56 +function extend(source) { 1.57 + let rest = Array.slice(arguments, 1); 1.58 + rest.unshift(Object.create(source)); 1.59 + return merge.apply(null, rest); 1.60 +} 1.61 +exports.extend = extend; 1.62 + 1.63 +function has(obj, key) obj.hasOwnProperty(key); 1.64 +exports.has = has; 1.65 + 1.66 +function each(obj, fn) { 1.67 + for (let key in obj) has(obj, key) && fn(obj[key], key, obj); 1.68 +} 1.69 +exports.each = each; 1.70 + 1.71 +/** 1.72 + * Like `merge`, except no property descriptors are manipulated, for use 1.73 + * with platform objects. Identical to underscore's `extend`. Useful for 1.74 + * merging XPCOM objects 1.75 + */ 1.76 +function safeMerge(source) { 1.77 + Array.slice(arguments, 1).forEach(function onEach (obj) { 1.78 + for (let prop in obj) source[prop] = obj[prop]; 1.79 + }); 1.80 + return source; 1.81 +} 1.82 +exports.safeMerge = safeMerge; 1.83 + 1.84 +/* 1.85 + * Returns a copy of the object without blacklisted properties 1.86 + */ 1.87 +function omit(source, ...values) { 1.88 + let copy = {}; 1.89 + let keys = flatten(values); 1.90 + for (let prop in source) 1.91 + if (!~keys.indexOf(prop)) 1.92 + copy[prop] = source[prop]; 1.93 + return copy; 1.94 +} 1.95 +exports.omit = omit;