-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
Copy pathcopy.js
120 lines (101 loc) · 2.98 KB
/
copy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { assert, deprecate } from '@ember/debug';
import EmberObject from './system/object';
import Copyable from './mixins/copyable';
/**
@module @ember/object
*/
function _copy(obj, deep, seen, copies) {
// primitive data types are immutable, just return them.
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let ret, loc;
// avoid cyclical loops
if (deep && (loc = seen.indexOf(obj)) >= 0) {
return copies[loc];
}
if (deep) {
seen.push(obj);
}
// IMPORTANT: this specific test will detect a native array only. Any other
// object will need to implement Copyable.
if (Array.isArray(obj)) {
ret = obj.slice();
if (deep) {
copies.push(ret);
loc = ret.length;
while (--loc >= 0) {
ret[loc] = _copy(ret[loc], deep, seen, copies);
}
}
} else if (Copyable.detect(obj)) {
ret = obj.copy(deep, seen, copies);
if (deep) {
copies.push(ret);
}
} else if (obj instanceof Date) {
ret = new Date(obj.getTime());
if (deep) {
copies.push(ret);
}
} else {
assert(
'Cannot clone an EmberObject that does not implement Copyable',
!(obj instanceof EmberObject) || Copyable.detect(obj)
);
ret = {};
if (deep) {
copies.push(ret);
}
let key;
for (key in obj) {
// support Null prototype
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
continue;
}
// Prevents browsers that don't respect non-enumerability from
// copying internal Ember properties
if (key.substring(0, 2) === '__') {
continue;
}
ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
}
}
return ret;
}
/**
Creates a shallow copy of the passed object. A deep copy of the object is
returned if the optional `deep` argument is `true`.
If the passed object implements the `Copyable` interface, then this
function will delegate to the object's `copy()` method and return the
result. See `Copyable` for further details.
For primitive values (which are immutable in JavaScript), the passed object
is simply returned.
@method copy
@deprecated Use 'ember-copy' addon instead
@static
@for @ember/object/internals
@param {Object} obj The object to clone
@param {Boolean} [deep=false] If true, a deep copy of the object is made.
@return {Object} The copied object
@public
*/
export default function copy(obj, deep) {
deprecate('Use ember-copy addon instead of copy method and Copyable mixin.', false, {
id: 'ember-runtime.deprecate-copy-copyable',
until: '4.0.0',
url: 'https://deprecations.emberjs.com/v3.x/#toc_ember-runtime-deprecate-copy-copyable',
for: 'ember-source',
since: {
enabled: '3.3.0',
},
});
// fast paths
if ('object' !== typeof obj || obj === null) {
return obj; // can't copy primitives
}
if (!Array.isArray(obj) && Copyable.detect(obj)) {
return obj.copy(deep);
}
return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
}