Initial commit
[yaffs-website] / node_modules / gulp / node_modules / clone / clone.js
1 'use strict';
2
3 function objectToString(o) {
4   return Object.prototype.toString.call(o);
5 }
6
7 // shim for Node's 'util' package
8 // DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/).
9 var util = {
10   isArray: function (ar) {
11     return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]');
12   },
13   isDate: function (d) {
14     return typeof d === 'object' && objectToString(d) === '[object Date]';
15   },
16   isRegExp: function (re) {
17     return typeof re === 'object' && objectToString(re) === '[object RegExp]';
18   },
19   getRegExpFlags: function (re) {
20     var flags = '';
21     re.global && (flags += 'g');
22     re.ignoreCase && (flags += 'i');
23     re.multiline && (flags += 'm');
24     return flags;
25   }
26 };
27
28
29 if (typeof module === 'object')
30   module.exports = clone;
31
32 /**
33  * Clones (copies) an Object using deep copying.
34  *
35  * This function supports circular references by default, but if you are certain
36  * there are no circular references in your object, you can save some CPU time
37  * by calling clone(obj, false).
38  *
39  * Caution: if `circular` is false and `parent` contains circular references,
40  * your program may enter an infinite loop and crash.
41  *
42  * @param `parent` - the object to be cloned
43  * @param `circular` - set to true if the object to be cloned may contain
44  *    circular references. (optional - true by default)
45  * @param `depth` - set to a number if the object is only to be cloned to
46  *    a particular depth. (optional - defaults to Infinity)
47  * @param `prototype` - sets the prototype to be used when cloning an object.
48  *    (optional - defaults to parent prototype).
49 */
50
51 function clone(parent, circular, depth, prototype) {
52   // maintain two arrays for circular references, where corresponding parents
53   // and children have the same index
54   var allParents = [];
55   var allChildren = [];
56
57   var useBuffer = typeof Buffer != 'undefined';
58
59   if (typeof circular == 'undefined')
60     circular = true;
61
62   if (typeof depth == 'undefined')
63     depth = Infinity;
64
65   // recurse this function so we don't reset allParents and allChildren
66   function _clone(parent, depth) {
67     // cloning null always returns null
68     if (parent === null)
69       return null;
70
71     if (depth == 0)
72       return parent;
73
74     var child;
75     var proto;
76     if (typeof parent != 'object') {
77       return parent;
78     }
79
80     if (util.isArray(parent)) {
81       child = [];
82     } else if (util.isRegExp(parent)) {
83       child = new RegExp(parent.source, util.getRegExpFlags(parent));
84       if (parent.lastIndex) child.lastIndex = parent.lastIndex;
85     } else if (util.isDate(parent)) {
86       child = new Date(parent.getTime());
87     } else if (useBuffer && Buffer.isBuffer(parent)) {
88       child = new Buffer(parent.length);
89       parent.copy(child);
90       return child;
91     } else {
92       if (typeof prototype == 'undefined') {
93         proto = Object.getPrototypeOf(parent);
94         child = Object.create(proto);
95       }
96       else {
97         child = Object.create(prototype);
98         proto = prototype;
99       }
100     }
101
102     if (circular) {
103       var index = allParents.indexOf(parent);
104
105       if (index != -1) {
106         return allChildren[index];
107       }
108       allParents.push(parent);
109       allChildren.push(child);
110     }
111
112     for (var i in parent) {
113       var attrs;
114       if (proto) {
115         attrs = Object.getOwnPropertyDescriptor(proto, i);
116       }
117       
118       if (attrs && attrs.set == null) {
119         continue;
120       }
121       child[i] = _clone(parent[i], depth - 1);
122     }
123
124     return child;
125   }
126
127   return _clone(parent, depth);
128 }
129
130 /**
131  * Simple flat clone using prototype, accepts only objects, usefull for property
132  * override on FLAT configuration object (no nested props).
133  *
134  * USE WITH CAUTION! This may not behave as you wish if you do not know how this
135  * works.
136  */
137 clone.clonePrototype = function(parent) {
138   if (parent === null)
139     return null;
140
141   var c = function () {};
142   c.prototype = parent;
143   return new c();
144 };