Skip to content

Commit f15dc32

Browse files
committed
no longer alter Object __proto__
1 parent 3fc48db commit f15dc32

File tree

6 files changed

+35
-43
lines changed

6 files changed

+35
-43
lines changed

changes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ Vue.config.debug = true
441441

442442
- #### New config option: `proto`
443443

444-
Be default, Vue.js alters observed data objects' `__proto__` when available for faster method interception/augmentation. This is perfectly fine when your data objects are plain JSON-derived objects. However if you want to use Vue's observation on object created with custom prototypes (e.g. from constructors), you can set `Vue.config.proto = false` to prohibit this behavior.
444+
Be default, Vue.js alters the `__proto__` of observed Arrays when available for faster method interception/augmentation. This would only cause issue in the rare case when you are observing a subclass of the native Array. In that case, you can set `Vue.config.proto = false` to prohibit this behavior.
445445

446446
## Transition API Change
447447

src/observer/array.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
var _ = require('../util')
2-
var arrayAugmentations = Object.create(Array.prototype)
2+
var arrayProto = Array.prototype
3+
var arrayMethods = Object.create(arrayProto)
34

45
/**
56
* Intercept mutating methods and emit events
@@ -16,8 +17,8 @@ var arrayAugmentations = Object.create(Array.prototype)
1617
]
1718
.forEach(function (method) {
1819
// cache original method
19-
var original = Array.prototype[method]
20-
_.define(arrayAugmentations, method, function mutator () {
20+
var original = arrayProto[method]
21+
_.define(arrayMethods, method, function mutator () {
2122
// avoid leaking arguments:
2223
// http://jsperf.com/closure-with-arguments
2324
var i = arguments.length
@@ -56,7 +57,7 @@ var arrayAugmentations = Object.create(Array.prototype)
5657
*/
5758

5859
_.define(
59-
arrayAugmentations,
60+
arrayProto,
6061
'$set',
6162
function $set (index, val) {
6263
if (index >= this.length) {
@@ -74,7 +75,7 @@ _.define(
7475
*/
7576

7677
_.define(
77-
arrayAugmentations,
78+
arrayProto,
7879
'$remove',
7980
function $remove (index) {
8081
if (typeof index !== 'number') {
@@ -86,4 +87,4 @@ _.define(
8687
}
8788
)
8889

89-
module.exports = arrayAugmentations
90+
module.exports = arrayMethods

src/observer/index.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
var _ = require('../util')
22
var config = require('../config')
33
var Binding = require('../binding')
4-
var arrayAugmentations = require('./array')
5-
var objectAugmentations = require('./object')
6-
var arrayKeys = Object.getOwnPropertyNames(arrayAugmentations)
7-
var objectKeys = Object.getOwnPropertyNames(objectAugmentations)
4+
var arrayMethods = require('./array')
5+
var arrayKeys = Object.getOwnPropertyNames(arrayMethods)
6+
require('./object')
87

98
var uid = 0
109

@@ -61,14 +60,13 @@ function Observer (value, type) {
6160
this.active = true
6261
this.bindings = []
6362
_.define(value, '__ob__', this)
64-
var augment = config.proto && _.hasProto
65-
? protoAugment
66-
: copyAugment
6763
if (type === ARRAY) {
68-
augment(value, arrayAugmentations, arrayKeys)
64+
var augment = config.proto && _.hasProto
65+
? protoAugment
66+
: copyAugment
67+
augment(value, arrayMethods, arrayKeys)
6968
this.observeArray(value)
7069
} else if (type === OBJECT) {
71-
augment(value, objectAugmentations, objectKeys)
7270
this.walk(value)
7371
}
7472
}

src/observer/object.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var _ = require('../util')
2-
var objectAgumentations = Object.create(Object.prototype)
2+
var objProto = Object.prototype
33

44
/**
55
* Add a new property to an observed object
@@ -11,15 +11,19 @@ var objectAgumentations = Object.create(Object.prototype)
1111
*/
1212

1313
_.define(
14-
objectAgumentations,
14+
objProto,
1515
'$add',
1616
function $add (key, val) {
17+
var ob = this.__ob__
18+
if (!ob) {
19+
this[key] = val
20+
return
21+
}
1722
if (_.isReserved(key)) {
1823
_.warn('Refused to $add reserved key: ' + key)
1924
return
2025
}
2126
if (this.hasOwnProperty(key)) return
22-
var ob = this.__ob__
2327
ob.convert(key, val)
2428
if (ob.vms) {
2529
var i = ob.vms.length
@@ -43,16 +47,20 @@ _.define(
4347
*/
4448

4549
_.define(
46-
objectAgumentations,
50+
objProto,
4751
'$delete',
4852
function $delete (key) {
53+
var ob = this.__ob__
54+
if (!ob) {
55+
delete this[key]
56+
return
57+
}
4958
if (_.isReserved(key)) {
5059
_.warn('Refused to $add reserved key: ' + key)
5160
return
5261
}
5362
if (!this.hasOwnProperty(key)) return
5463
delete this[key]
55-
var ob = this.__ob__
5664
if (ob.vms) {
5765
var i = ob.vms.length
5866
while (i--) {
@@ -64,6 +72,4 @@ _.define(
6472
ob.notify()
6573
}
6674
}
67-
)
68-
69-
module.exports = objectAgumentations
75+
)

src/parse/path.js

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -287,31 +287,14 @@ exports.set = function (obj, path, val) {
287287
obj = obj[key]
288288
if (!_.isObject(obj)) {
289289
obj = {}
290-
add(last, key, obj)
290+
last.$add(key, obj)
291291
}
292292
}
293293
key = path[i]
294294
if (key in obj) {
295295
obj[key] = val
296296
} else {
297-
add(obj, key, val)
298-
}
299-
return true
300-
}
301-
302-
/**
303-
* Add a property to an object, using $add if target
304-
* has been augmented by Vue's observer.
305-
*
306-
* @param {Object} obj
307-
* @param {String} key
308-
* @param {*} val
309-
*/
310-
311-
function add (obj, key, val) {
312-
if (obj.$add) {
313297
obj.$add(key, val)
314-
} else {
315-
obj[key] = val
316298
}
299+
return true
317300
}

test/unit/specs/observer_spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ describe('Observer', function () {
108108
// should ignore deleting non-existing key
109109
obj.$delete('a')
110110
expect(binding.notify.calls.count()).toBe(2)
111+
// should work on non-observed objects
112+
var obj2 = { a: 1 }
113+
obj2.$delete('a')
114+
expect(obj2.hasOwnProperty('a')).toBe(false)
111115
})
112116

113117
it('observing array mutation', function () {

0 commit comments

Comments
 (0)