2
2
3
3
var hasOwn = Object . prototype . hasOwnProperty ;
4
4
var toStr = Object . prototype . toString ;
5
+ var defineProperty = Object . defineProperty ;
6
+ var gOPD = Object . getOwnPropertyDescriptor ;
5
7
6
8
var isArray = function isArray ( arr ) {
7
9
if ( typeof Array . isArray === 'function' ) {
@@ -31,6 +33,35 @@ var isPlainObject = function isPlainObject(obj) {
31
33
return typeof key === 'undefined' || hasOwn . call ( obj , key ) ;
32
34
} ;
33
35
36
+ // If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target
37
+ var setProperty = function setProperty ( target , options ) {
38
+ if ( defineProperty && options . name === '__proto__' ) {
39
+ defineProperty ( target , options . name , {
40
+ enumerable : true ,
41
+ configurable : true ,
42
+ value : options . newValue ,
43
+ writable : true
44
+ } ) ;
45
+ } else {
46
+ target [ options . name ] = options . newValue ;
47
+ }
48
+ } ;
49
+
50
+ // Return undefined instead of __proto__ if '__proto__' is not an own property
51
+ var getProperty = function getProperty ( obj , name ) {
52
+ if ( name === '__proto__' ) {
53
+ if ( ! hasOwn . call ( obj , name ) ) {
54
+ return void 0 ;
55
+ } else if ( gOPD ) {
56
+ // In early versions of node, obj['__proto__'] is buggy when obj has
57
+ // __proto__ as an own property. Object.getOwnPropertyDescriptor() works.
58
+ return gOPD ( obj , name ) . value ;
59
+ }
60
+ }
61
+
62
+ return obj [ name ] ;
63
+ } ;
64
+
34
65
module . exports = function extend ( ) {
35
66
var options , name , src , copy , copyIsArray , clone ;
36
67
var target = arguments [ 0 ] ;
@@ -55,8 +86,8 @@ module.exports = function extend() {
55
86
if ( options != null ) {
56
87
// Extend the base object
57
88
for ( name in options ) {
58
- src = target [ name ] ;
59
- copy = options [ name ] ;
89
+ src = getProperty ( target , name ) ;
90
+ copy = getProperty ( options , name ) ;
60
91
61
92
// Prevent never-ending loop
62
93
if ( target !== copy ) {
@@ -70,11 +101,11 @@ module.exports = function extend() {
70
101
}
71
102
72
103
// Never move original objects, clone them
73
- target [ name ] = extend ( deep , clone , copy ) ;
104
+ setProperty ( target , { name : name , newValue : extend ( deep , clone , copy ) } ) ;
74
105
75
106
// Don't bring in undefined values
76
107
} else if ( typeof copy !== 'undefined' ) {
77
- target [ name ] = copy ;
108
+ setProperty ( target , { name : name , newValue : copy } ) ;
78
109
}
79
110
}
80
111
}
0 commit comments