@@ -36,48 +36,26 @@ module.exports = internals.clone = function (obj, options = {}, _seen = null) {
3636 }
3737 }
3838
39+ // Built-in object types
40+
3941 const baseProto = Types . getInternalProto ( obj ) ;
40- let newObj ;
41-
42- switch ( baseProto ) {
43- case Types . buffer :
44- return Buffer && Buffer . from ( obj ) ; // $lab:coverage:ignore$
45-
46- case Types . date :
47- return new Date ( obj . getTime ( ) ) ;
48-
49- case Types . regex :
50- return new RegExp ( obj ) ;
51-
52- case Types . array :
53- newObj = [ ] ;
54- break ;
55-
56- default :
57- if ( options . prototype !== false ) { // Defaults to true
58- const proto = Object . getPrototypeOf ( obj ) ;
59- if ( proto &&
60- proto . isImmutable ) {
61-
62- return obj ;
63- }
64-
65- if ( internals . needsProtoHack . has ( baseProto ) ) {
66- newObj = new proto . constructor ( ) ;
67- if ( proto !== baseProto ) {
68- Object . setPrototypeOf ( newObj , proto ) ;
69- }
70- }
71- else {
72- newObj = Object . create ( proto ) ;
73- }
74- }
75- else if ( internals . needsProtoHack . has ( baseProto ) ) {
76- newObj = new baseProto . constructor ( ) ;
77- }
78- else {
79- newObj = { } ;
80- }
42+ if ( baseProto === Types . buffer ) {
43+ return Buffer && Buffer . from ( obj ) ; // $lab:coverage:ignore$
44+ }
45+
46+ if ( baseProto === Types . date ) {
47+ return new Date ( obj . getTime ( ) ) ;
48+ }
49+
50+ if ( baseProto === Types . regex ) {
51+ return new RegExp ( obj ) ;
52+ }
53+
54+ // Generic objects
55+
56+ const newObj = internals . base ( obj , baseProto , options ) ;
57+ if ( newObj === obj ) {
58+ return obj ;
8159 }
8260
8361 if ( seen ) {
@@ -96,35 +74,38 @@ module.exports = internals.clone = function (obj, options = {}, _seen = null) {
9674 }
9775
9876 const keys = Utils . keys ( obj , options ) ;
99- for ( let i = 0 ; i < keys . length ; ++ i ) {
100- const key = keys [ i ] ;
101-
77+ for ( const key of keys ) {
10278 if ( baseProto === Types . array &&
10379 key === 'length' ) {
10480
81+ newObj . length = obj . length ;
10582 continue ;
10683 }
10784
10885 const descriptor = Object . getOwnPropertyDescriptor ( obj , key ) ;
109- if ( descriptor &&
110- ( descriptor . get || descriptor . set ) ) {
86+ if ( descriptor ) {
87+ if ( descriptor . get ||
88+ descriptor . set ) {
11189
112- Object . defineProperty ( newObj , key , descriptor ) ;
90+ Object . defineProperty ( newObj , key , descriptor ) ;
91+ }
92+ else if ( descriptor . enumerable ) {
93+ newObj [ key ] = clone ( obj [ key ] , options , seen ) ;
94+ }
95+ else {
96+ Object . defineProperty ( newObj , key , { enumerable : false , writable : true , configurable : true , value : clone ( obj [ key ] , options , seen ) } ) ;
97+ }
11398 }
11499 else {
115100 Object . defineProperty ( newObj , key , {
116- enumerable : descriptor ? descriptor . enumerable : true ,
101+ enumerable : true ,
117102 writable : true ,
118103 configurable : true ,
119104 value : clone ( obj [ key ] , options , seen )
120105 } ) ;
121106 }
122107 }
123108
124- if ( baseProto === Types . array ) {
125- newObj . length = obj . length ;
126- }
127-
128109 return newObj ;
129110} ;
130111
@@ -140,3 +121,37 @@ internals.cloneWithShallow = function (source, options) {
140121 Utils . restore ( copy , source , storage ) ; // Shallow copy the stored items and restore
141122 return copy ;
142123} ;
124+
125+
126+ internals . base = function ( obj , baseProto , options ) {
127+
128+ if ( baseProto === Types . array ) {
129+ return [ ] ;
130+ }
131+
132+ if ( options . prototype === false ) { // Defaults to true
133+ if ( internals . needsProtoHack . has ( baseProto ) ) {
134+ return new baseProto . constructor ( ) ;
135+ }
136+
137+ return { } ;
138+ }
139+
140+ const proto = Object . getPrototypeOf ( obj ) ;
141+ if ( proto &&
142+ proto . isImmutable ) {
143+
144+ return obj ;
145+ }
146+
147+ if ( internals . needsProtoHack . has ( baseProto ) ) {
148+ const newObj = new proto . constructor ( ) ;
149+ if ( proto !== baseProto ) {
150+ Object . setPrototypeOf ( newObj , proto ) ;
151+ }
152+
153+ return newObj ;
154+ }
155+
156+ return Object . create ( proto ) ;
157+ } ;
0 commit comments